Browse Source

move gencs/genjava's configure function inside generate, because it actually generates stuff, not merely configures

Dan Korostelev 8 years ago
parent
commit
fa88aae010
2 changed files with 2458 additions and 2474 deletions
  1. 2428 2436
      src/generators/gencs.ml
  2. 30 38
      src/generators/genjava.ml

+ 2428 - 2436
src/generators/gencs.ml

@@ -648,2627 +648,2619 @@ let rec get_fun_modifiers meta access modifiers =
 		| (Meta.Custom ("?prop_impl" | ":cs_event_impl"),[],_) :: meta -> get_fun_modifiers meta "private" modifiers
 		| _ :: meta -> get_fun_modifiers meta access modifiers
 
-(* this was the way I found to pass the generator context to be accessible across all functions here *)
-(* so 'configure' is almost 'top-level' and will have all functions needed to make this work *)
-let configure gen =
-	let native_arr_cl = get_cl ( get_type gen (["cs"], "NativeArray") ) in
-	gen.gclasses.nativearray <- (fun t -> TInst(native_arr_cl,[t]));
-	gen.gclasses.nativearray_type <- (function TInst(_,[t]) -> t | _ -> assert false);
-	gen.gclasses.nativearray_len <- (fun e p -> mk_field_access gen e "Length" p);
+let generate con =
+	(try
+		let gen = new_ctx con in
+		let basic = con.basic in
 
-	let basic = gen.gcon.basic in
+		if Common.defined_value con Define.Dce = "no" then begin
+			let m = { null_module with m_id = alloc_mid(); m_path = ["haxe";"lang"],"DceNo" } in
+			let cl = mk_class m (["haxe";"lang"],"DceNo") null_pos in
+			gen.gtypes_list <- (TClassDecl cl) :: gen.gtypes_list;
+			Hashtbl.add gen.gtypes cl.cl_path (TClassDecl cl)
+		end;
 
-	let erase_generics = Common.defined gen.gcon Define.EraseGenerics in
-	let fn_cl = get_cl (get_type gen (["haxe";"lang"],"Function")) in
-	let null_t = if erase_generics then null_class else (get_cl (get_type gen (["haxe";"lang"],"Null")) ) in
-	let runtime_cl = get_cl (get_type gen (["haxe";"lang"],"Runtime")) in
-	let no_root = Common.defined gen.gcon Define.NoRoot in
-	let change_id name = try
-			Hashtbl.find reserved name
-		with | Not_found ->
-			let ret = String.concat "." (String.nsplit name "#") in
-			List.hd (String.nsplit ret "`")
-	in
+		(* make the basic functions in C# *)
+		let type_cl = get_cl ( get_type gen (["System"], "Type")) in
+		let basic_fns =
+		[
+			mk_class_field "Equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true null_pos (Method MethNormal) [];
+			mk_class_field "ToString" (TFun([], basic.tstring)) true null_pos (Method MethNormal) [];
+			mk_class_field "GetHashCode" (TFun([], basic.tint)) true null_pos (Method MethNormal) [];
+			mk_class_field "GetType" (TFun([], TInst(type_cl, []))) true null_pos (Method MethNormal) [];
+		] in
+		List.iter (fun cf -> gen.gbase_class_fields <- PMap.add cf.cf_name cf gen.gbase_class_fields) basic_fns;
 
-	let change_clname n = change_id n in
-
-	let change_ns_params_root md ns params =
-		let ns,params = List.fold_left (fun (ns,params) nspart -> try
-			let part, nparams = String.split nspart "`" in
-			let nparams = int_of_string nparams in
-			let rec loop i needed params =
-				if i = nparams then
-					(List.rev needed,params)
-				else
-					loop (i+1) (List.hd params :: needed) (List.tl params)
+		let native_arr_cl = get_cl ( get_type gen (["cs"], "NativeArray") ) in
+		gen.gclasses.nativearray <- (fun t -> TInst(native_arr_cl,[t]));
+		gen.gclasses.nativearray_type <- (function TInst(_,[t]) -> t | _ -> assert false);
+		gen.gclasses.nativearray_len <- (fun e p -> mk_field_access gen e "Length" p);
+
+		let erase_generics = Common.defined gen.gcon Define.EraseGenerics in
+		let fn_cl = get_cl (get_type gen (["haxe";"lang"],"Function")) in
+		let null_t = if erase_generics then null_class else (get_cl (get_type gen (["haxe";"lang"],"Null")) ) in
+		let runtime_cl = get_cl (get_type gen (["haxe";"lang"],"Runtime")) in
+		let no_root = Common.defined gen.gcon Define.NoRoot in
+		let change_id name = try
+				Hashtbl.find reserved name
+			with | Not_found ->
+				let ret = String.concat "." (String.nsplit name "#") in
+				List.hd (String.nsplit ret "`")
+		in
+
+		let change_clname n = change_id n in
+
+		let change_ns_params_root md ns params =
+			let ns,params = List.fold_left (fun (ns,params) nspart -> try
+				let part, nparams = String.split nspart "`" in
+				let nparams = int_of_string nparams in
+				let rec loop i needed params =
+					if i = nparams then
+						(List.rev needed,params)
+					else
+						loop (i+1) (List.hd params :: needed) (List.tl params)
+				in
+				let needed,params = loop 0 [] params in
+				let part = change_id part in
+				(part ^ "<" ^ (String.concat ", " needed) ^ ">")::ns, params
+			with _ -> (* Invalid_string / int_of_string *)
+				(change_id nspart)::ns, params
+			) ([],params) ns
 			in
-			let needed,params = loop 0 [] params in
-			let part = change_id part in
-			(part ^ "<" ^ (String.concat ", " needed) ^ ">")::ns, params
-		with _ -> (* Invalid_string / int_of_string *)
-			(change_id nspart)::ns, params
-		) ([],params) ns
+			List.rev ns,params
 		in
-		List.rev ns,params
-	in
 
-	let change_ns_params md params ns = if no_root then (
-		let needs_root md = is_hxgen md || match md with
-			| TClassDecl cl when (Meta.has Meta.Enum cl.cl_meta) && (Meta.has Meta.CompilerGenerated cl.cl_meta) ->
-				(* this will match our compiler-generated enum constructor classes *)
-				true
-			| _ ->
-				false
+		let change_ns_params md params ns = if no_root then (
+			let needs_root md = is_hxgen md || match md with
+				| TClassDecl cl when (Meta.has Meta.Enum cl.cl_meta) && (Meta.has Meta.CompilerGenerated cl.cl_meta) ->
+					(* this will match our compiler-generated enum constructor classes *)
+					true
+				| _ ->
+					false
+			in
+			match ns with
+				| [] when needs_root md -> ["haxe";"root"], params
+				| [s] when (t_infos md).mt_private && needs_root md -> ["haxe";"root";s], params
+				| [] -> (match md with
+					| TClassDecl { cl_path = ([],"Std" | [],"Math") } -> ["haxe";"root"], params
+					| TClassDecl { cl_meta = m } when Meta.has Meta.Enum m -> ["haxe";"root"], params
+					| _ -> [], params)
+				| ns when params = [] -> List.map change_id ns, params
+				| ns ->
+					change_ns_params_root md ns params)
+			else if params = [] then
+				List.map change_id ns, params
+			else
+				change_ns_params_root md ns params
 		in
-		match ns with
-			| [] when needs_root md -> ["haxe";"root"], params
-			| [s] when (t_infos md).mt_private && needs_root md -> ["haxe";"root";s], params
-			| [] -> (match md with
-				| TClassDecl { cl_path = ([],"Std" | [],"Math") } -> ["haxe";"root"], params
-				| TClassDecl { cl_meta = m } when Meta.has Meta.Enum m -> ["haxe";"root"], params
-				| _ -> [], params)
-			| ns when params = [] -> List.map change_id ns, params
-			| ns ->
-				change_ns_params_root md ns params)
-		else if params = [] then
-			List.map change_id ns, params
-		else
-			change_ns_params_root md ns params
-	in
 
-	let change_ns md ns =
-		let ns, _ = change_ns_params md [] ns in
-		ns
-	in
+		let change_ns md ns =
+			let ns, _ = change_ns_params md [] ns in
+			ns
+		in
 
-	let change_field = change_id in
-	let write_id w name = write w (change_id name) in
-	let write_field w name = write w (change_field name) in
+		let change_field = change_id in
+		let write_id w name = write w (change_id name) in
+		let write_field w name = write w (change_field name) in
 
-	let ptr =
-		if Common.defined gen.gcon Define.Unsafe then
-			get_abstract (get_type gen (["cs"],"Pointer"))
-		else
-			null_abstract
-	in
+		let ptr =
+			if Common.defined gen.gcon Define.Unsafe then
+				get_abstract (get_type gen (["cs"],"Pointer"))
+			else
+				null_abstract
+		in
 
-	let is_hxgeneric md =
-		TypeParams.RealTypeParams.is_hxgeneric md
-	in
+		let is_hxgeneric md =
+			TypeParams.RealTypeParams.is_hxgeneric md
+		in
 
-	let rec field_is_hxgeneric e = match e.eexpr with
-		| TParenthesis e | TMeta(_,e) -> field_is_hxgeneric e
-		| TField(_, (FStatic(cl,_) | FInstance(cl,_,_)) ) ->
-			(* print_endline ("is_hxgeneric " ^ s_type_path cl.cl_path ^ " : " ^ string_of_bool (is_hxgeneric (TClassDecl cl))); *)
-			is_hxgeneric (TClassDecl cl)
-		| _ -> true
-	in
+		let rec field_is_hxgeneric e = match e.eexpr with
+			| TParenthesis e | TMeta(_,e) -> field_is_hxgeneric e
+			| TField(_, (FStatic(cl,_) | FInstance(cl,_,_)) ) ->
+				(* print_endline ("is_hxgeneric " ^ s_type_path cl.cl_path ^ " : " ^ string_of_bool (is_hxgeneric (TClassDecl cl))); *)
+				is_hxgeneric (TClassDecl cl)
+			| _ -> true
+		in
 
-	gen.gfollow#add "follow_basic" PZero (fun t -> match t with
-			| TAbstract ({ a_path = ([], "Bool") },[])
-			| TAbstract ({ a_path = ([], "Void") },[])
-			| TAbstract ({ a_path = ([],"Float") },[])
-			| TAbstract ({ a_path = ([],"Int") },[])
-			| TAbstract ({ a_path = [],"UInt" },[])
-			| TType ({ t_path = ["cs"], "Int64" },[])
-			| TAbstract ({ a_path = ["cs"], "Int64" },[])
-			| TType ({ t_path = ["cs"],"UInt64" },[])
-			| TAbstract ({ a_path = ["cs"],"UInt64" },[])
-			| TType ({ t_path = ["cs"],"UInt8" },[])
-			| TAbstract ({ a_path = ["cs"],"UInt8" },[])
-			| TType ({ t_path = ["cs"],"Int8" },[])
-			| TAbstract ({ a_path = ["cs"],"Int8" },[])
-			| TType ({ t_path = ["cs"],"Int16" },[])
-			| TAbstract ({ a_path = ["cs"],"Int16" },[])
-			| TType ({ t_path = ["cs"],"UInt16" },[])
-			| TAbstract ({ a_path = ["cs"],"UInt16" },[])
-			| TType ({ t_path = ["cs"],"Char16" },[])
-			| TAbstract ({ a_path = ["cs"],"Char16" },[])
-			| TType ({ t_path = ["cs"],"Ref" },_)
-			| TAbstract ({ a_path = ["cs"],"Ref" },_)
-			| TType ({ t_path = ["cs"],"Out" },_)
-			| TAbstract ({ a_path = ["cs"],"Out" },_)
-			| TType ({ t_path = [],"Single" },[])
-			| TAbstract ({ a_path = [],"Single" },[]) -> Some t
-			| TType (({ t_path = [],"Null" } as tdef),[t2]) ->
-					Some (TType(tdef,[follow (gen.gfollow#run_f t2)]))
-			| TAbstract({ a_path = ["cs"],"PointerAccess" },[t]) ->
-					Some (TAbstract(ptr,[t]))
-			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-					Some (gen.gfollow#run_f ( Abstract.get_underlying_type a pl) )
-			| TAbstract( { a_path = ([], "EnumValue") }, _	)
-			| TInst( { cl_path = ([], "EnumValue") }, _  ) -> Some t_dynamic
-			| _ -> None);
-
-	let module_s_params md params =
-		let md = change_md md in
-		let path = (t_infos md).mt_path in
-		match path with
-			| ([], "String") -> "string", params
-			| ([], "Null") -> s_type_path (change_ns md ["haxe"; "lang"], change_clname "Null"), params
-			| (ns,clname) ->
-				let ns, params = change_ns_params md params ns in
-				s_type_path (ns, change_clname clname), params
-	in
+		gen.gfollow#add "follow_basic" PZero (fun t -> match t with
+				| TAbstract ({ a_path = ([], "Bool") },[])
+				| TAbstract ({ a_path = ([], "Void") },[])
+				| TAbstract ({ a_path = ([],"Float") },[])
+				| TAbstract ({ a_path = ([],"Int") },[])
+				| TAbstract ({ a_path = [],"UInt" },[])
+				| TType ({ t_path = ["cs"], "Int64" },[])
+				| TAbstract ({ a_path = ["cs"], "Int64" },[])
+				| TType ({ t_path = ["cs"],"UInt64" },[])
+				| TAbstract ({ a_path = ["cs"],"UInt64" },[])
+				| TType ({ t_path = ["cs"],"UInt8" },[])
+				| TAbstract ({ a_path = ["cs"],"UInt8" },[])
+				| TType ({ t_path = ["cs"],"Int8" },[])
+				| TAbstract ({ a_path = ["cs"],"Int8" },[])
+				| TType ({ t_path = ["cs"],"Int16" },[])
+				| TAbstract ({ a_path = ["cs"],"Int16" },[])
+				| TType ({ t_path = ["cs"],"UInt16" },[])
+				| TAbstract ({ a_path = ["cs"],"UInt16" },[])
+				| TType ({ t_path = ["cs"],"Char16" },[])
+				| TAbstract ({ a_path = ["cs"],"Char16" },[])
+				| TType ({ t_path = ["cs"],"Ref" },_)
+				| TAbstract ({ a_path = ["cs"],"Ref" },_)
+				| TType ({ t_path = ["cs"],"Out" },_)
+				| TAbstract ({ a_path = ["cs"],"Out" },_)
+				| TType ({ t_path = [],"Single" },[])
+				| TAbstract ({ a_path = [],"Single" },[]) -> Some t
+				| TType (({ t_path = [],"Null" } as tdef),[t2]) ->
+						Some (TType(tdef,[follow (gen.gfollow#run_f t2)]))
+				| TAbstract({ a_path = ["cs"],"PointerAccess" },[t]) ->
+						Some (TAbstract(ptr,[t]))
+				| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
+						Some (gen.gfollow#run_f ( Abstract.get_underlying_type a pl) )
+				| TAbstract( { a_path = ([], "EnumValue") }, _	)
+				| TInst( { cl_path = ([], "EnumValue") }, _  ) -> Some t_dynamic
+				| _ -> None);
+
+		let module_s_params md params =
+			let md = change_md md in
+			let path = (t_infos md).mt_path in
+			match path with
+				| ([], "String") -> "string", params
+				| ([], "Null") -> s_type_path (change_ns md ["haxe"; "lang"], change_clname "Null"), params
+				| (ns,clname) ->
+					let ns, params = change_ns_params md params ns in
+					s_type_path (ns, change_clname clname), params
+		in
 
-	let module_s md =
-		fst (module_s_params md [])
-	in
+		let module_s md =
+			fst (module_s_params md [])
+		in
 
-	let ifaces = Hashtbl.create 1 in
+		let ifaces = Hashtbl.create 1 in
 
-	let ti64 = match ( get_type gen (["cs"], "Int64") ) with | TTypeDecl t -> TType(t,[]) | TAbstractDecl a -> TAbstract(a,[]) | _ -> assert false in
+		let ti64 = match ( get_type gen (["cs"], "Int64") ) with | TTypeDecl t -> TType(t,[]) | TAbstractDecl a -> TAbstract(a,[]) | _ -> assert false in
 
-	let ttype = get_cl ( get_type gen (["System"], "Type") ) in
+		let ttype = get_cl ( get_type gen (["System"], "Type") ) in
 
-	let has_tdyn tl =
-		List.exists (fun t -> match follow t with
-		| TDynamic _ | TMono _ -> true
-		| _ -> false
-	) tl
-	in
+		let has_tdyn tl =
+			List.exists (fun t -> match follow t with
+			| TDynamic _ | TMono _ -> true
+			| _ -> false
+		) tl
+		in
 
-	let rec real_type t =
-		let t = gen.gfollow#run_f t in
-		let ret = match t with
-			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-				real_type (Abstract.get_underlying_type a pl)
-			| TAbstract ({ a_path = (["cs";"_Flags"], "EnumUnderlying") }, [t]) ->
-				real_type t
-			| TInst( { cl_path = (["cs";"system"], "String") }, [] ) ->
-				gen.gcon.basic.tstring;
-			| TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint
-			| TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64
-			| TAbstract( { a_path = [],"Class" }, _ )
-			| TAbstract( { a_path = [],"Enum" }, _ )
-			| TAbstract( { a_path = ["haxe";"extern"],"Rest" }, _ )
-			| TInst( { cl_path = ([], "Class") }, _ )
-			| TInst( { cl_path = ([], "Enum") }, _ ) -> TInst(ttype,[])
-			| TInst( ({ cl_kind = KTypeParameter _ } as cl), _ ) when erase_generics && not (Meta.has Meta.NativeGeneric cl.cl_meta) ->
-				t_dynamic
-			| TInst({ cl_kind = KExpr _ }, _) -> t_dynamic
-			| TEnum(_, [])
-			| TInst(_, []) -> t
-			| TInst(cl, params) when
-				has_tdyn params &&
-				Hashtbl.mem ifaces cl.cl_path ->
-					TInst(Hashtbl.find ifaces cl.cl_path, [])
-			| TEnum(e, params) ->
-				TEnum(e, List.map (fun _ -> t_dynamic) params)
-			| TInst(cl, params) when Meta.has Meta.Enum cl.cl_meta ->
-				TInst(cl, List.map (fun _ -> t_dynamic) params)
-			| TInst(cl, params) -> TInst(cl, change_param_type (TClassDecl cl) params)
-			| TType({ t_path = ([], "Null") }, [t]) ->
+		let rec real_type t =
+			let t = gen.gfollow#run_f t in
+			let ret = match t with
+				| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
+					real_type (Abstract.get_underlying_type a pl)
+				| TAbstract ({ a_path = (["cs";"_Flags"], "EnumUnderlying") }, [t]) ->
+					real_type t
+				| TInst( { cl_path = (["cs";"system"], "String") }, [] ) ->
+					gen.gcon.basic.tstring;
+				| TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint
+				| TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64
+				| TAbstract( { a_path = [],"Class" }, _ )
+				| TAbstract( { a_path = [],"Enum" }, _ )
+				| TAbstract( { a_path = ["haxe";"extern"],"Rest" }, _ )
+				| TInst( { cl_path = ([], "Class") }, _ )
+				| TInst( { cl_path = ([], "Enum") }, _ ) -> TInst(ttype,[])
+				| TInst( ({ cl_kind = KTypeParameter _ } as cl), _ ) when erase_generics && not (Meta.has Meta.NativeGeneric cl.cl_meta) ->
+					t_dynamic
+				| TInst({ cl_kind = KExpr _ }, _) -> t_dynamic
+				| TEnum(_, [])
+				| TInst(_, []) -> t
+				| TInst(cl, params) when
+					has_tdyn params &&
+					Hashtbl.mem ifaces cl.cl_path ->
+						TInst(Hashtbl.find ifaces cl.cl_path, [])
+				| TEnum(e, params) ->
+					TEnum(e, List.map (fun _ -> t_dynamic) params)
+				| TInst(cl, params) when Meta.has Meta.Enum cl.cl_meta ->
+					TInst(cl, List.map (fun _ -> t_dynamic) params)
+				| TInst(cl, params) -> TInst(cl, change_param_type (TClassDecl cl) params)
+				| TType({ t_path = ([], "Null") }, [t]) ->
+					(*
+						Null<> handling is a little tricky.
+						It will only change to haxe.lang.Null<> when the actual type is non-nullable or a type parameter
+						It works on cases such as Hash<T> returning Null<T> since cast_detect will invoke real_type at the original type,
+						Null<T>, which will then return the type haxe.lang.Null<>
+					*)
+					if erase_generics then
+						if is_cs_basic_type t then
+							t_dynamic
+						else
+							real_type t
+					else
+						(match real_type t with
+							| TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t])
+							| t when is_cs_basic_type t -> TInst(null_t, [t])
+							| _ -> real_type t)
+				| TAbstract _
+				| TType _ -> t
+				| TAnon (anon) when (match !(anon.a_status) with | Statics _ | EnumStatics _ | AbstractStatics _ -> true | _ -> false) -> t
+				| TFun _ -> TInst(fn_cl,[])
+				| _ -> t_dynamic
+			in
+			ret
+		and
+
+		(*
+			On hxcs, the only type parameters allowed to be declared are the basic c# types.
+			That's made like this to avoid casting problems when type parameters in this case
+			add nothing to performance, since the memory layout is always the same.
+
+			To avoid confusion between Generic<Dynamic> (which has a different meaning in hxcs AST),
+			all those references are using dynamic_anon, which means Generic<{}>
+		*)
+		change_param_type md tl =
+			let types = match md with
+				| TClassDecl c -> c.cl_params
+				| TEnumDecl e -> []
+				| TAbstractDecl a -> a.a_params
+				| TTypeDecl t -> t.t_params
+			in
+			let is_hxgeneric = if types = [] then is_hxgen md else (TypeParams.RealTypeParams.is_hxgeneric md) in
+			let ret t =
+				let t_changed = real_type t in
+				match is_hxgeneric, t_changed with
+				| false, _ -> t
 				(*
-					Null<> handling is a little tricky.
-					It will only change to haxe.lang.Null<> when the actual type is non-nullable or a type parameter
-					It works on cases such as Hash<T> returning Null<T> since cast_detect will invoke real_type at the original type,
-					Null<T>, which will then return the type haxe.lang.Null<>
+					Because Null<> types need a special compiler treatment for many operations (e.g. boxing/unboxing),
+					Null<> type parameters will be transformed into Dynamic.
 				*)
-				if erase_generics then
-					if is_cs_basic_type t then
-						t_dynamic
-					else
-						real_type t
-				else
-					(match real_type t with
-						| TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t])
-						| t when is_cs_basic_type t -> TInst(null_t, [t])
-						| _ -> real_type t)
-			| TAbstract _
-			| TType _ -> t
-			| TAnon (anon) when (match !(anon.a_status) with | Statics _ | EnumStatics _ | AbstractStatics _ -> true | _ -> false) -> t
-			| TFun _ -> TInst(fn_cl,[])
-			| _ -> t_dynamic
+				| true, TInst ( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> dynamic_anon
+				| true, TInst ( { cl_kind = KTypeParameter _ }, _ ) -> t
+				| true, TInst _
+				| true, TEnum _
+				| true, TAbstract _ when is_cs_basic_type t_changed -> t
+				| true, TDynamic _ -> t
+				| true, x ->
+					dynamic_anon
+			in
+			if is_hxgeneric && (erase_generics || List.exists (fun t -> match follow t with | TDynamic _ -> true | _ -> false) tl) then
+				List.map (fun _ -> t_dynamic) tl
+			else
+				List.map ret tl
 		in
-		ret
-	and
-
-	(*
-		On hxcs, the only type parameters allowed to be declared are the basic c# types.
-		That's made like this to avoid casting problems when type parameters in this case
-		add nothing to performance, since the memory layout is always the same.
 
-		To avoid confusion between Generic<Dynamic> (which has a different meaning in hxcs AST),
-		all those references are using dynamic_anon, which means Generic<{}>
-	*)
-	change_param_type md tl =
-		let types = match md with
-			| TClassDecl c -> c.cl_params
-			| TEnumDecl e -> []
-			| TAbstractDecl a -> a.a_params
-			| TTypeDecl t -> t.t_params
-		in
-		let is_hxgeneric = if types = [] then is_hxgen md else (TypeParams.RealTypeParams.is_hxgeneric md) in
-		let ret t =
-			let t_changed = real_type t in
-			match is_hxgeneric, t_changed with
-			| false, _ -> t
-			(*
-				Because Null<> types need a special compiler treatment for many operations (e.g. boxing/unboxing),
-				Null<> type parameters will be transformed into Dynamic.
-			*)
-			| true, TInst ( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> dynamic_anon
-			| true, TInst ( { cl_kind = KTypeParameter _ }, _ ) -> t
-			| true, TInst _
-			| true, TEnum _
-			| true, TAbstract _ when is_cs_basic_type t_changed -> t
-			| true, TDynamic _ -> t
-			| true, x ->
-				dynamic_anon
+		let is_dynamic t = match real_type t with
+			| TMono _ | TDynamic _
+			| TInst({ cl_kind = KTypeParameter _ }, _) -> true
+			| TAnon anon ->
+				(match !(anon.a_status) with
+					| EnumStatics _ | Statics _ -> false
+					| _ -> true
+				)
+			| _ -> false
 		in
-		if is_hxgeneric && (erase_generics || List.exists (fun t -> match follow t with | TDynamic _ -> true | _ -> false) tl) then
-			List.map (fun _ -> t_dynamic) tl
-		else
-			List.map ret tl
-	in
 
-	let is_dynamic t = match real_type t with
-		| TMono _ | TDynamic _
-		| TInst({ cl_kind = KTypeParameter _ }, _) -> true
-		| TAnon anon ->
-			(match !(anon.a_status) with
-				| EnumStatics _ | Statics _ -> false
-				| _ -> true
-			)
-		| _ -> false
-	in
-
-	let rec t_s t =
-		match real_type t with
-			(* basic types *)
-			| TAbstract ({ a_path = ([], "Bool") },[]) -> "bool"
-			| TAbstract ({ a_path = ([], "Void") },[]) -> "object"
-			| TAbstract ({ a_path = ([],"Float") },[]) -> "double"
-			| TAbstract ({ a_path = ([],"Int") },[]) -> "int"
-			| TAbstract ({ a_path = [],"UInt" },[]) -> "uint"
-			| TType ({ t_path = ["cs"], "Int64" },[])
-			| TAbstract ({ a_path = ["cs"], "Int64" },[]) -> "long"
-			| TType ({ t_path = ["cs"],"UInt64" },[])
-			| TAbstract ({ a_path = ["cs"],"UInt64" },[]) -> "ulong"
-			| TType ({ t_path = ["cs"],"UInt8" },[])
-			| TAbstract ({ a_path = ["cs"],"UInt8" },[]) -> "byte"
-			| TType ({ t_path = ["cs"],"Int8" },[])
-			| TAbstract ({ a_path = ["cs"],"Int8" },[]) -> "sbyte"
-			| TType ({ t_path = ["cs"],"Int16" },[])
-			| TAbstract ({ a_path = ["cs"],"Int16" },[]) -> "short"
-			| TType ({ t_path = ["cs"],"UInt16" },[])
-			| TAbstract ({ a_path = ["cs"],"UInt16" },[]) -> "ushort"
-			| TType ({ t_path = ["cs"],"Char16" },[])
-			| TAbstract ({ a_path = ["cs"],"Char16" },[]) -> "char"
-			| TType ({ t_path = [],"Single" },[])
-			| TAbstract ({ a_path = [],"Single" },[]) -> "float"
-			| TInst ({ cl_path = ["haxe"],"Int32" },[])
-			| TAbstract ({ a_path = ["haxe"],"Int32" },[]) -> "int"
-			| TInst ({ cl_path = ["haxe"],"Int64" },[])
-			| TAbstract ({ a_path = ["haxe"],"Int64" },[]) -> "long"
-			| TInst ({ cl_path = ([], "Dynamic") },_)
-			| TAbstract ({ a_path = ([], "Dynamic") },_) -> "object"
-			| TType ({ t_path = ["cs"],"Out" },[t])
-			| TAbstract ({ a_path = ["cs"],"Out" },[t])
-			| TType ({ t_path = ["cs"],"Ref" },[t])
-			| TAbstract ({ a_path = ["cs"],"Ref" },[t]) -> t_s t
-			| TInst({ cl_path = (["cs"], "NativeArray") }, [param]) ->
-				let rec check_t_s t =
-					match real_type t with
-						| TInst({ cl_path = (["cs"], "NativeArray") }, [param]) ->
-							(check_t_s param) ^ "[]"
-						| _ -> t_s (run_follow gen t)
-				in
-				(check_t_s param) ^ "[]"
-			| TInst({ cl_path = (["cs"], "Pointer") },[t])
-			| TAbstract({ a_path = (["cs"], "Pointer") },[t])->
-				let ret = t_s t in
-				(if ret = "object" then "void" else ret) ^ "*"
-			(* end of basic types *)
-			| TInst ({ cl_kind = KTypeParameter _; cl_path=p }, []) -> snd p
-			| TMono r -> (match !r with | None -> "object" | Some t -> t_s (run_follow gen t))
-			| TInst ({ cl_path = [], "String" }, []) -> "string"
-			| TEnum (e, params) -> ("global::" ^ (module_s (TEnumDecl e)))
-			| TInst (cl, _ :: _) when Meta.has Meta.Enum cl.cl_meta ->
-				"global::" ^ module_s (TClassDecl cl)
-			| TInst (({ cl_path = p } as cl), params) -> (path_param_s (TClassDecl cl) p params)
-			| TType (({ t_path = p } as t), params) -> (path_param_s (TTypeDecl t) p params)
-			| TAnon (anon) ->
-				(match !(anon.a_status) with
-					| Statics _ | EnumStatics _ -> "System.Type"
-					| _ -> "object")
-			| TDynamic _ -> "object"
-			| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-				t_s (Abstract.get_underlying_type a pl)
-			(* No Lazy type nor Function type made. That's because function types will be at this point be converted into other types *)
-			| _ -> if !strict_mode then begin trace ("[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"); assert false end else "[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"
-
-	and path_param_s md path params =
-			match params with
-				| [] -> "global::" ^ module_s md
-				| _ when erase_generics && is_hxgeneric md ->
-					"global::" ^ module_s md
-				| _ ->
-					let params = (List.map (fun t -> t_s t) (change_param_type md params)) in
-					let str,params = module_s_params md params in
-					if params = [] then
-						"global::" ^ str
-					else
-						sprintf "global::%s<%s>" str (String.concat ", " params)
-	in
+		let rec t_s t =
+			match real_type t with
+				(* basic types *)
+				| TAbstract ({ a_path = ([], "Bool") },[]) -> "bool"
+				| TAbstract ({ a_path = ([], "Void") },[]) -> "object"
+				| TAbstract ({ a_path = ([],"Float") },[]) -> "double"
+				| TAbstract ({ a_path = ([],"Int") },[]) -> "int"
+				| TAbstract ({ a_path = [],"UInt" },[]) -> "uint"
+				| TType ({ t_path = ["cs"], "Int64" },[])
+				| TAbstract ({ a_path = ["cs"], "Int64" },[]) -> "long"
+				| TType ({ t_path = ["cs"],"UInt64" },[])
+				| TAbstract ({ a_path = ["cs"],"UInt64" },[]) -> "ulong"
+				| TType ({ t_path = ["cs"],"UInt8" },[])
+				| TAbstract ({ a_path = ["cs"],"UInt8" },[]) -> "byte"
+				| TType ({ t_path = ["cs"],"Int8" },[])
+				| TAbstract ({ a_path = ["cs"],"Int8" },[]) -> "sbyte"
+				| TType ({ t_path = ["cs"],"Int16" },[])
+				| TAbstract ({ a_path = ["cs"],"Int16" },[]) -> "short"
+				| TType ({ t_path = ["cs"],"UInt16" },[])
+				| TAbstract ({ a_path = ["cs"],"UInt16" },[]) -> "ushort"
+				| TType ({ t_path = ["cs"],"Char16" },[])
+				| TAbstract ({ a_path = ["cs"],"Char16" },[]) -> "char"
+				| TType ({ t_path = [],"Single" },[])
+				| TAbstract ({ a_path = [],"Single" },[]) -> "float"
+				| TInst ({ cl_path = ["haxe"],"Int32" },[])
+				| TAbstract ({ a_path = ["haxe"],"Int32" },[]) -> "int"
+				| TInst ({ cl_path = ["haxe"],"Int64" },[])
+				| TAbstract ({ a_path = ["haxe"],"Int64" },[]) -> "long"
+				| TInst ({ cl_path = ([], "Dynamic") },_)
+				| TAbstract ({ a_path = ([], "Dynamic") },_) -> "object"
+				| TType ({ t_path = ["cs"],"Out" },[t])
+				| TAbstract ({ a_path = ["cs"],"Out" },[t])
+				| TType ({ t_path = ["cs"],"Ref" },[t])
+				| TAbstract ({ a_path = ["cs"],"Ref" },[t]) -> t_s t
+				| TInst({ cl_path = (["cs"], "NativeArray") }, [param]) ->
+					let rec check_t_s t =
+						match real_type t with
+							| TInst({ cl_path = (["cs"], "NativeArray") }, [param]) ->
+								(check_t_s param) ^ "[]"
+							| _ -> t_s (run_follow gen t)
+					in
+					(check_t_s param) ^ "[]"
+				| TInst({ cl_path = (["cs"], "Pointer") },[t])
+				| TAbstract({ a_path = (["cs"], "Pointer") },[t])->
+					let ret = t_s t in
+					(if ret = "object" then "void" else ret) ^ "*"
+				(* end of basic types *)
+				| TInst ({ cl_kind = KTypeParameter _; cl_path=p }, []) -> snd p
+				| TMono r -> (match !r with | None -> "object" | Some t -> t_s (run_follow gen t))
+				| TInst ({ cl_path = [], "String" }, []) -> "string"
+				| TEnum (e, params) -> ("global::" ^ (module_s (TEnumDecl e)))
+				| TInst (cl, _ :: _) when Meta.has Meta.Enum cl.cl_meta ->
+					"global::" ^ module_s (TClassDecl cl)
+				| TInst (({ cl_path = p } as cl), params) -> (path_param_s (TClassDecl cl) p params)
+				| TType (({ t_path = p } as t), params) -> (path_param_s (TTypeDecl t) p params)
+				| TAnon (anon) ->
+					(match !(anon.a_status) with
+						| Statics _ | EnumStatics _ -> "System.Type"
+						| _ -> "object")
+				| TDynamic _ -> "object"
+				| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
+					t_s (Abstract.get_underlying_type a pl)
+				(* No Lazy type nor Function type made. That's because function types will be at this point be converted into other types *)
+				| _ -> if !strict_mode then begin trace ("[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"); assert false end else "[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"
+
+		and path_param_s md path params =
+				match params with
+					| [] -> "global::" ^ module_s md
+					| _ when erase_generics && is_hxgeneric md ->
+						"global::" ^ module_s md
+					| _ ->
+						let params = (List.map (fun t -> t_s t) (change_param_type md params)) in
+						let str,params = module_s_params md params in
+						if params = [] then
+							"global::" ^ str
+						else
+							sprintf "global::%s<%s>" str (String.concat ", " params)
+		in
 
-	let rett_s t =
-		match t with
-			| TAbstract ({ a_path = ([], "Void") },[]) -> "void"
-			| _ -> t_s t
-	in
+		let rett_s t =
+			match t with
+				| TAbstract ({ a_path = ([], "Void") },[]) -> "void"
+				| _ -> t_s t
+		in
 
-	let escape ichar b =
-		match ichar with
-			| 92 (* \ *) -> Buffer.add_string b "\\\\"
-			| 39 (* ' *) -> Buffer.add_string b "\\\'"
-			| 34 -> Buffer.add_string b "\\\""
-			| 13 (* \r *) -> Buffer.add_string b "\\r"
-			| 10 (* \n *) -> Buffer.add_string b "\\n"
-			| 9 (* \t *) -> Buffer.add_string b "\\t"
-			| c when c < 32 || (c >= 127 && c <= 0xFFFF) -> Buffer.add_string b (Printf.sprintf "\\u%.4x" c)
-			| c when c > 0xFFFF -> Buffer.add_string b (Printf.sprintf "\\U%.8x" c)
-			| c -> Buffer.add_char b (Char.chr c)
-	in
+		let escape ichar b =
+			match ichar with
+				| 92 (* \ *) -> Buffer.add_string b "\\\\"
+				| 39 (* ' *) -> Buffer.add_string b "\\\'"
+				| 34 -> Buffer.add_string b "\\\""
+				| 13 (* \r *) -> Buffer.add_string b "\\r"
+				| 10 (* \n *) -> Buffer.add_string b "\\n"
+				| 9 (* \t *) -> Buffer.add_string b "\\t"
+				| c when c < 32 || (c >= 127 && c <= 0xFFFF) -> Buffer.add_string b (Printf.sprintf "\\u%.4x" c)
+				| c when c > 0xFFFF -> Buffer.add_string b (Printf.sprintf "\\U%.8x" c)
+				| c -> Buffer.add_char b (Char.chr c)
+		in
 
-	let escape s =
-		let b = Buffer.create 0 in
-		(try
-			UTF8.validate s;
-			UTF8.iter (fun c -> escape (UChar.code c) b) s
-		with
-			UTF8.Malformed_code ->
-				String.iter (fun c -> escape (Char.code c) b) s
-		);
-		Buffer.contents b
-	in
+		let escape s =
+			let b = Buffer.create 0 in
+			(try
+				UTF8.validate s;
+				UTF8.iter (fun c -> escape (UChar.code c) b) s
+			with
+				UTF8.Malformed_code ->
+					String.iter (fun c -> escape (Char.code c) b) s
+			);
+			Buffer.contents b
+		in
 
-	let has_semicolon e =
-		match e.eexpr with
-			| TBlock _ | TFor _ | TSwitch _ | TTry _ | TIf _ -> false
-			| TWhile (_,_,flag) when flag = Ast.NormalWhile -> false
-			| _ -> true
-	in
+		let has_semicolon e =
+			match e.eexpr with
+				| TBlock _ | TFor _ | TSwitch _ | TTry _ | TIf _ -> false
+				| TWhile (_,_,flag) when flag = Ast.NormalWhile -> false
+				| _ -> true
+		in
 
-	let in_value = ref false in
-
-	let rec md_s md =
-		let md = follow_module (gen.gfollow#run_f) md in
-		match md with
-			| TClassDecl ({ cl_params = [] } as cl) ->
-				t_s (TInst(cl,[]))
-			| TClassDecl (cl) when not (is_hxgen md) ->
-				t_s (TInst(cl,List.map (fun t -> t_dynamic) cl.cl_params))
-			| TEnumDecl ({ e_params = [] } as e) ->
-				t_s (TEnum(e,[]))
-			| TEnumDecl (e) when not (is_hxgen md) ->
-				t_s (TEnum(e,List.map (fun t -> t_dynamic) e.e_params))
-			| TClassDecl cl ->
-				t_s (TInst(cl,[]))
-			| TEnumDecl e ->
-				t_s (TEnum(e,[]))
-			| TTypeDecl t ->
-				t_s (TType(t, List.map (fun t -> t_dynamic) t.t_params))
-			| TAbstractDecl a ->
-				t_s (TAbstract(a, List.map(fun t -> t_dynamic) a.a_params))
-	in
+		let in_value = ref false in
+
+		let rec md_s md =
+			let md = follow_module (gen.gfollow#run_f) md in
+			match md with
+				| TClassDecl ({ cl_params = [] } as cl) ->
+					t_s (TInst(cl,[]))
+				| TClassDecl (cl) when not (is_hxgen md) ->
+					t_s (TInst(cl,List.map (fun t -> t_dynamic) cl.cl_params))
+				| TEnumDecl ({ e_params = [] } as e) ->
+					t_s (TEnum(e,[]))
+				| TEnumDecl (e) when not (is_hxgen md) ->
+					t_s (TEnum(e,List.map (fun t -> t_dynamic) e.e_params))
+				| TClassDecl cl ->
+					t_s (TInst(cl,[]))
+				| TEnumDecl e ->
+					t_s (TEnum(e,[]))
+				| TTypeDecl t ->
+					t_s (TType(t, List.map (fun t -> t_dynamic) t.t_params))
+				| TAbstractDecl a ->
+					t_s (TAbstract(a, List.map(fun t -> t_dynamic) a.a_params))
+		in
 
-	let rec ensure_local e explain =
-		match e.eexpr with
-			| TLocal _ -> e
-			| TCast(e,_)
-			| TParenthesis e | TMeta(_,e) -> ensure_local e explain
-			| _ -> gen.gcon.error ("This function argument " ^ explain ^ " must be a local variable.") e.epos; e
-	in
+		let rec ensure_local e explain =
+			match e.eexpr with
+				| TLocal _ -> e
+				| TCast(e,_)
+				| TParenthesis e | TMeta(_,e) -> ensure_local e explain
+				| _ -> gen.gcon.error ("This function argument " ^ explain ^ " must be a local variable.") e.epos; e
+		in
 
-	let rec ensure_refout e explain =
-		match e.eexpr with
-			| TField _ | TLocal _ -> e
-			| TCast(e,_)
-			| TParenthesis e | TMeta(_,e) -> ensure_refout e explain
-			| _ -> gen.gcon.error ("This function argument " ^ explain ^ " must be a local variable.") e.epos; e
-	in
+		let rec ensure_refout e explain =
+			match e.eexpr with
+				| TField _ | TLocal _ -> e
+				| TCast(e,_)
+				| TParenthesis e | TMeta(_,e) -> ensure_refout e explain
+				| _ -> gen.gcon.error ("This function argument " ^ explain ^ " must be a local variable.") e.epos; e
+		in
 
-	let last_line = ref (-1) in
-	let begin_block w = write w "{"; push_indent w; newline w; last_line := -1 in
-	let end_block w = pop_indent w; (if w.sw_has_content then newline w); write w "}"; newline w; last_line := -1 in
-	let skip_line_directives = (not gen.gcon.debug && not (Common.defined gen.gcon Define.NoCompilation)) || Common.defined gen.gcon Define.RealPosition in
-	let line_directive =
-		if skip_line_directives then
-			fun w p -> ()
-		else fun w p ->
-			if p.pfile <> null_pos.pfile then (* Compiler Error CS1560 https://msdn.microsoft.com/en-us/library/z3t5e5sw(v=vs.90).aspx *)
-			let cur_line = Lexer.get_error_line p in
-			let file = Path.get_full_path p.pfile in
-			if cur_line <> ((!last_line)+1) then
-				let line = Ast.s_escape file in
-				if String.length line <= 256 then
-					begin print w "#line %d \"%s\"" cur_line line; newline w end
-				else (* Compiler Error CS1560 https://msdn.microsoft.com/en-us/library/z3t5e5sw(v=vs.90).aspx *)
-					begin print w "//line %d \"%s\"" cur_line line; newline w end;
-			last_line := cur_line
-	in
-	let line_reset_directive =
-		if skip_line_directives then
-			fun w -> ()
-		else fun w ->
-			print w "#line default"
-	in
+		let last_line = ref (-1) in
+		let begin_block w = write w "{"; push_indent w; newline w; last_line := -1 in
+		let end_block w = pop_indent w; (if w.sw_has_content then newline w); write w "}"; newline w; last_line := -1 in
+		let skip_line_directives = (not gen.gcon.debug && not (Common.defined gen.gcon Define.NoCompilation)) || Common.defined gen.gcon Define.RealPosition in
+		let line_directive =
+			if skip_line_directives then
+				fun w p -> ()
+			else fun w p ->
+				if p.pfile <> null_pos.pfile then (* Compiler Error CS1560 https://msdn.microsoft.com/en-us/library/z3t5e5sw(v=vs.90).aspx *)
+				let cur_line = Lexer.get_error_line p in
+				let file = Path.get_full_path p.pfile in
+				if cur_line <> ((!last_line)+1) then
+					let line = Ast.s_escape file in
+					if String.length line <= 256 then
+						begin print w "#line %d \"%s\"" cur_line line; newline w end
+					else (* Compiler Error CS1560 https://msdn.microsoft.com/en-us/library/z3t5e5sw(v=vs.90).aspx *)
+						begin print w "//line %d \"%s\"" cur_line line; newline w end;
+				last_line := cur_line
+		in
+		let line_reset_directive =
+			if skip_line_directives then
+				fun w -> ()
+			else fun w ->
+				print w "#line default"
+		in
 
-	let rec extract_tparams params el =
-		match el with
-			| ({ eexpr = TLocal({ v_name = "$type_param" }) } as tp) :: tl ->
-				extract_tparams (tp.etype :: params) tl
-			| _ -> (params, el)
-	in
+		let rec extract_tparams params el =
+			match el with
+				| ({ eexpr = TLocal({ v_name = "$type_param" }) } as tp) :: tl ->
+					extract_tparams (tp.etype :: params) tl
+				| _ -> (params, el)
+		in
 
-	let is_extern_prop t name = match follow (run_follow gen t), field_access gen t name with
-		| TInst({ cl_interface = true; cl_extern = true } as cl, _), FNotFound ->
-			not (is_hxgen (TClassDecl cl))
-		| _, FClassField(_,_,decl,v,_,t,_) ->
-			Type.is_extern_field v && (Meta.has Meta.Property v.cf_meta || (decl.cl_extern && not (is_hxgen (TClassDecl decl))))
-		| _ -> false
-	in
+		let is_extern_prop t name = match follow (run_follow gen t), field_access gen t name with
+			| TInst({ cl_interface = true; cl_extern = true } as cl, _), FNotFound ->
+				not (is_hxgen (TClassDecl cl))
+			| _, FClassField(_,_,decl,v,_,t,_) ->
+				Type.is_extern_field v && (Meta.has Meta.Property v.cf_meta || (decl.cl_extern && not (is_hxgen (TClassDecl decl))))
+			| _ -> false
+		in
 
-	let is_event t name = match follow (run_follow gen t), field_access gen t name with
-		| TInst({ cl_interface = true; cl_extern = true } as cl, _), FNotFound ->
-			not (is_hxgen (TClassDecl cl))
-		| _, FClassField(_,_,decl,v,_,_,_) ->
-			Meta.has Meta.Event v.cf_meta
-		| _ -> false
-	in
+		let is_event t name = match follow (run_follow gen t), field_access gen t name with
+			| TInst({ cl_interface = true; cl_extern = true } as cl, _), FNotFound ->
+				not (is_hxgen (TClassDecl cl))
+			| _, FClassField(_,_,decl,v,_,_,_) ->
+				Meta.has Meta.Event v.cf_meta
+			| _ -> false
+		in
 
-	let extract_statements expr =
-		let ret = ref [] in
-		let rec loop expr = match expr.eexpr with
-			| TCall ({ eexpr = TLocal {
-					v_name = "__is__" | "__typeof__" | "__array__" | "__sizeof__" | "__delegate__"
-				} }, el) ->
-				List.iter loop el
-			| TNew ({ cl_path = (["cs"], "NativeArray") }, params, [ size ]) ->
-				()
-			| TUnop (Ast.Increment, _, _)
-			| TUnop (Ast.Decrement, _, _)
-			| TBinop (Ast.OpAssign, _, _)
-			| TBinop (Ast.OpAssignOp _, _, _)
-			| TLocal { v_name = "__fallback__" }
-			| TLocal { v_name = "__sbreak__" } ->
-				ret := expr :: !ret
-			| TConst _
-			| TLocal _
-			| TArray _
-			| TBinop _
-			| TField _
-			| TEnumParameter _
-			| TTypeExpr _
-			| TObjectDecl _
-			| TArrayDecl _
-			| TCast _
-			| TMeta _
-			| TParenthesis _
-			| TUnop _ ->
-				Type.iter loop expr
-			| TFunction _ -> () (* do not extract parameters from inside of it *)
-			| _ ->
-				ret := expr :: !ret
+		let extract_statements expr =
+			let ret = ref [] in
+			let rec loop expr = match expr.eexpr with
+				| TCall ({ eexpr = TLocal {
+						v_name = "__is__" | "__typeof__" | "__array__" | "__sizeof__" | "__delegate__"
+					} }, el) ->
+					List.iter loop el
+				| TNew ({ cl_path = (["cs"], "NativeArray") }, params, [ size ]) ->
+					()
+				| TUnop (Ast.Increment, _, _)
+				| TUnop (Ast.Decrement, _, _)
+				| TBinop (Ast.OpAssign, _, _)
+				| TBinop (Ast.OpAssignOp _, _, _)
+				| TLocal { v_name = "__fallback__" }
+				| TLocal { v_name = "__sbreak__" } ->
+					ret := expr :: !ret
+				| TConst _
+				| TLocal _
+				| TArray _
+				| TBinop _
+				| TField _
+				| TEnumParameter _
+				| TTypeExpr _
+				| TObjectDecl _
+				| TArrayDecl _
+				| TCast _
+				| TMeta _
+				| TParenthesis _
+				| TUnop _ ->
+					Type.iter loop expr
+				| TFunction _ -> () (* do not extract parameters from inside of it *)
+				| _ ->
+					ret := expr :: !ret
+			in
+			loop expr;
+			(* [expr] *)
+			List.rev !ret
 		in
-		loop expr;
-		(* [expr] *)
-		List.rev !ret
-	in
 
-	let expr_s w e =
-		last_line := -1;
-		in_value := false;
-		let rec expr_s w e =
-			let was_in_value = !in_value in
-			in_value := true;
-			(match e.eexpr with
-				| TCall({ eexpr = TField(ef,f) }, (_ :: _ as args) ) when (field_name f) = "get_Item" ->
-					expr_s w ef;
-					write w "[";
-					let first = ref true in
-					List.iter (fun f ->
-						if !first then first := false else write w ", ";
-						expr_s w f
-					) args;
-					write w "]"
-				| TCall({ eexpr = TField(ef,f) }, (_ :: _ :: _ as args) ) when (field_name f) = "set_Item" ->
-					expr_s w ef;
-					write w "[";
-					let args, value = match List.rev args with
-						| v :: args -> List.rev args, v
-						| _ -> assert false
-					in
-					let first = ref true in
-					List.iter (fun f ->
-						if !first then first := false else write w ", ";
-						expr_s w f
-					) args;
-					write w "] = ";
-					expr_s w value
-				| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "add_" ->
-					let name = field_name f in
-					let propname = String.sub name 4 (String.length name - 4) in
-					if is_event (gen.greal_type ef.etype) propname then begin
-						expr_s w ef;
-						write w ".";
-						write_field w propname;
-						write w " += ";
-						expr_s w ev
-					end else
-						do_call w e [ev]
-				| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "remove_" ->
-					let name = field_name f in
-					let propname = String.sub name 7 (String.length name - 7) in
-					if is_event (gen.greal_type ef.etype) propname then begin
+		let expr_s w e =
+			last_line := -1;
+			in_value := false;
+			let rec expr_s w e =
+				let was_in_value = !in_value in
+				in_value := true;
+				(match e.eexpr with
+					| TCall({ eexpr = TField(ef,f) }, (_ :: _ as args) ) when (field_name f) = "get_Item" ->
 						expr_s w ef;
-						write w ".";
-						write_field w propname;
-						write w " -= ";
-						expr_s w ev
-					end else
-						do_call w e [ev]
-				| TCall( ({ eexpr = TField(ef,f) } as e), [] ) when String.starts_with (field_name f) "get_" ->
-					let name = field_name f in
-					let propname = String.sub name 4 (String.length name - 4) in
-					if is_extern_prop (gen.greal_type ef.etype) propname then begin
-						expr_s w ef;
-						write w ".";
-						write_field w propname
-					end else
-						do_call w e []
-				| TCall( ({ eexpr = TField(ef,f) } as e), [v] ) when String.starts_with (field_name f) "set_" ->
-					let name = field_name f in
-					let propname = String.sub name 4 (String.length name - 4) in
-					if is_extern_prop (gen.greal_type ef.etype) propname then begin
+						write w "[";
+						let first = ref true in
+						List.iter (fun f ->
+							if !first then first := false else write w ", ";
+							expr_s w f
+						) args;
+						write w "]"
+					| TCall({ eexpr = TField(ef,f) }, (_ :: _ :: _ as args) ) when (field_name f) = "set_Item" ->
 						expr_s w ef;
+						write w "[";
+						let args, value = match List.rev args with
+							| v :: args -> List.rev args, v
+							| _ -> assert false
+						in
+						let first = ref true in
+						List.iter (fun f ->
+							if !first then first := false else write w ", ";
+							expr_s w f
+						) args;
+						write w "] = ";
+						expr_s w value
+					| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "add_" ->
+						let name = field_name f in
+						let propname = String.sub name 4 (String.length name - 4) in
+						if is_event (gen.greal_type ef.etype) propname then begin
+							expr_s w ef;
+							write w ".";
+							write_field w propname;
+							write w " += ";
+							expr_s w ev
+						end else
+							do_call w e [ev]
+					| TCall( ({ eexpr = TField(ef,f) } as e), [ev] ) when String.starts_with (field_name f) "remove_" ->
+						let name = field_name f in
+						let propname = String.sub name 7 (String.length name - 7) in
+						if is_event (gen.greal_type ef.etype) propname then begin
+							expr_s w ef;
+							write w ".";
+							write_field w propname;
+							write w " -= ";
+							expr_s w ev
+						end else
+							do_call w e [ev]
+					| TCall( ({ eexpr = TField(ef,f) } as e), [] ) when String.starts_with (field_name f) "get_" ->
+						let name = field_name f in
+						let propname = String.sub name 4 (String.length name - 4) in
+						if is_extern_prop (gen.greal_type ef.etype) propname then begin
+							expr_s w ef;
+							write w ".";
+							write_field w propname
+						end else
+							do_call w e []
+					| TCall( ({ eexpr = TField(ef,f) } as e), [v] ) when String.starts_with (field_name f) "set_" ->
+						let name = field_name f in
+						let propname = String.sub name 4 (String.length name - 4) in
+						if is_extern_prop (gen.greal_type ef.etype) propname then begin
+							expr_s w ef;
+							write w ".";
+							write_field w propname;
+							write w " = ";
+							expr_s w v
+						end else
+							do_call w e [v]
+					| TField (e, (FStatic(_, cf) | FInstance(_, _, cf))) when Meta.has Meta.Native cf.cf_meta ->
+						let rec loop meta = match meta with
+							| (Meta.Native, [EConst (String s), _],_) :: _ ->
+								expr_s w e; write w "."; write_field w s
+							| _ :: tl -> loop tl
+							| [] -> expr_s w e; write w "."; write_field w (cf.cf_name)
+						in
+						loop cf.cf_meta
+					| TConst c ->
+						(match c with
+							| TInt i32 ->
+								write w (Int32.to_string i32);
+								(* these suffixes won't work because of the cast detector which will set each constant to its expected type *)
+								(*match real_type e.etype with
+									| TType( { t_path = (["haxe";"_Int64"], "NativeInt64") }, [] ) -> write w "L";
+									| _ -> ()
+								*)
+							| TFloat s ->
+								write w s;
+								(if String.get s (String.length s - 1) = '.' then write w "0");
+								(*match real_type e.etype with
+									| TType( { t_path = ([], "Single") }, [] ) -> write w "f"
+									| _ -> ()
+								*)
+							| TString s ->
+								write w "\"";
+								write w (escape s);
+								write w "\""
+							| TBool b -> write w (if b then "true" else "false")
+							| TNull when is_cs_basic_type e.etype || is_tparam e.etype ->
+								write w "default(";
+								write w (t_s e.etype);
+								write w ")"
+							| TNull -> write w "null"
+							| TThis -> write w "this"
+							| TSuper -> write w "base")
+					| TCast({ eexpr = TConst(TNull) }, _) ->
+								write w "default(";
+								write w (t_s e.etype);
+								write w ")"
+					| TLocal { v_name = "__sbreak__" } -> write w "break"
+					| TLocal { v_name = "__undefined__" } ->
+						write w (t_s (TInst(runtime_cl, List.map (fun _ -> t_dynamic) runtime_cl.cl_params)));
+						write w ".undefined";
+					| TLocal { v_name = "__typeof__" } -> write w "typeof"
+					| TLocal { v_name = "__sizeof__" } -> write w "sizeof"
+					| TLocal var ->
+						write_id w var.v_name
+					| TField (_, FEnum(e, ef)) ->
+						let s = ef.ef_name in
+						print w "%s." ("global::" ^ module_s (TEnumDecl e)); write_field w s
+					| TArray (e1, e2) ->
+						expr_s w e1; write w "["; expr_s w e2; write w "]"
+					| TBinop ((Ast.OpAssign as op), e1, e2)
+					| TBinop ((Ast.OpAssignOp _ as op), e1, e2) ->
+						expr_s w e1; write w ( " " ^ (Ast.s_binop op) ^ " " ); expr_s w e2
+					| TBinop (op, e1, e2) ->
+						write w "( ";
+						expr_s w e1; write w ( " " ^ (Ast.s_binop op) ^ " " ); expr_s w e2;
+						write w " )"
+					| TField ({ eexpr = TTypeExpr mt }, s) ->
+						(match mt with
+							| TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt)
+							| TClassDecl { cl_path = (["haxe"], "Int32") } -> write w ("global::" ^ module_s mt)
+							| TClassDecl { cl_interface = true } ->
+									write w ("global::" ^ module_s mt);
+									write w "__Statics_";
+							| TClassDecl cl -> write w (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_params)))
+							| TEnumDecl en -> write w (t_s (TEnum(en, List.map (fun _ -> t_empty) en.e_params)))
+							| TTypeDecl td -> write w (t_s (gen.gfollow#run_f (TType(td, List.map (fun _ -> t_empty) td.t_params))))
+							| TAbstractDecl a -> write w (t_s (TAbstract(a, List.map (fun _ -> t_empty) a.a_params)))
+						);
 						write w ".";
-						write_field w propname;
-						write w " = ";
-						expr_s w v
-					end else
-						do_call w e [v]
-				| TField (e, (FStatic(_, cf) | FInstance(_, _, cf))) when Meta.has Meta.Native cf.cf_meta ->
-					let rec loop meta = match meta with
-						| (Meta.Native, [EConst (String s), _],_) :: _ ->
-							expr_s w e; write w "."; write_field w s
-						| _ :: tl -> loop tl
-						| [] -> expr_s w e; write w "."; write_field w (cf.cf_name)
-					in
-					loop cf.cf_meta
-				| TConst c ->
-					(match c with
-						| TInt i32 ->
-							write w (Int32.to_string i32);
-							(* these suffixes won't work because of the cast detector which will set each constant to its expected type *)
-							(*match real_type e.etype with
-								| TType( { t_path = (["haxe";"_Int64"], "NativeInt64") }, [] ) -> write w "L";
-								| _ -> ()
-							*)
-						| TFloat s ->
-							write w s;
-							(if String.get s (String.length s - 1) = '.' then write w "0");
-							(*match real_type e.etype with
-								| TType( { t_path = ([], "Single") }, [] ) -> write w "f"
-								| _ -> ()
-							*)
-						| TString s ->
-							write w "\"";
-							write w (escape s);
-							write w "\""
-						| TBool b -> write w (if b then "true" else "false")
-						| TNull when is_cs_basic_type e.etype || is_tparam e.etype ->
-							write w "default(";
-							write w (t_s e.etype);
-							write w ")"
-						| TNull -> write w "null"
-						| TThis -> write w "this"
-						| TSuper -> write w "base")
-				| TCast({ eexpr = TConst(TNull) }, _) ->
-							write w "default(";
-							write w (t_s e.etype);
-							write w ")"
-				| TLocal { v_name = "__sbreak__" } -> write w "break"
-				| TLocal { v_name = "__undefined__" } ->
-					write w (t_s (TInst(runtime_cl, List.map (fun _ -> t_dynamic) runtime_cl.cl_params)));
-					write w ".undefined";
-				| TLocal { v_name = "__typeof__" } -> write w "typeof"
-				| TLocal { v_name = "__sizeof__" } -> write w "sizeof"
-				| TLocal var ->
-					write_id w var.v_name
-				| TField (_, FEnum(e, ef)) ->
-					let s = ef.ef_name in
-					print w "%s." ("global::" ^ module_s (TEnumDecl e)); write_field w s
-				| TArray (e1, e2) ->
-					expr_s w e1; write w "["; expr_s w e2; write w "]"
-				| TBinop ((Ast.OpAssign as op), e1, e2)
-				| TBinop ((Ast.OpAssignOp _ as op), e1, e2) ->
-					expr_s w e1; write w ( " " ^ (Ast.s_binop op) ^ " " ); expr_s w e2
-				| TBinop (op, e1, e2) ->
-					write w "( ";
-					expr_s w e1; write w ( " " ^ (Ast.s_binop op) ^ " " ); expr_s w e2;
-					write w " )"
-				| TField ({ eexpr = TTypeExpr mt }, s) ->
-					(match mt with
-						| TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt)
-						| TClassDecl { cl_path = (["haxe"], "Int32") } -> write w ("global::" ^ module_s mt)
-						| TClassDecl { cl_interface = true } ->
-								write w ("global::" ^ module_s mt);
-								write w "__Statics_";
-						| TClassDecl cl -> write w (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_params)))
-						| TEnumDecl en -> write w (t_s (TEnum(en, List.map (fun _ -> t_empty) en.e_params)))
-						| TTypeDecl td -> write w (t_s (gen.gfollow#run_f (TType(td, List.map (fun _ -> t_empty) td.t_params))))
-						| TAbstractDecl a -> write w (t_s (TAbstract(a, List.map (fun _ -> t_empty) a.a_params)))
-					);
-					write w ".";
-					write_field w (field_name s)
-				| TField (e, s) when is_pointer gen e.etype ->
-					(* take off the extra cast if possible *)
-					let e = match e.eexpr with
-						| TCast(e1,_) when CastDetect.type_iseq gen e.etype e1.etype ->
-							e1
-						| _ -> e
-					in
-					expr_s w e; write w "->"; write_field w (field_name s)
-				| TField (e, s) ->
-					expr_s w e; write w "."; write_field w (field_name s)
-				| TTypeExpr mt ->
-					(match change_md mt with
-						| TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt)
-						| TClassDecl { cl_path = (["haxe"], "Int32") } -> write w ("global::" ^ module_s mt)
-						| TClassDecl cl -> write w (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_params)));
-						| TEnumDecl en -> write w (t_s (TEnum(en, List.map (fun _ -> t_empty) en.e_params)))
-						| TTypeDecl td -> write w (t_s (gen.gfollow#run_f (TType(td, List.map (fun _ -> t_empty) td.t_params))))
-						| TAbstractDecl a -> write w (t_s (TAbstract(a, List.map (fun _ -> t_empty) a.a_params)))
-					)
-				| TParenthesis e ->
-					write w "("; expr_s w e; write w ")"
-				| TMeta (_,e) ->
-						expr_s w e
-				| TArrayDecl el
-				| TCall ({ eexpr = TLocal { v_name = "__array__" } }, el)
-				| TCall ({ eexpr = TField(_, FStatic({ cl_path = (["cs"],"NativeArray") }, { cf_name = "make" })) }, el) ->
-					let _, el = extract_tparams [] el in
-					print w "new %s" (t_s e.etype);
-					write w "{";
-					ignore (List.fold_left (fun acc e ->
-						(if acc <> 0 then write w ", ");
+						write_field w (field_name s)
+					| TField (e, s) when is_pointer gen e.etype ->
+						(* take off the extra cast if possible *)
+						let e = match e.eexpr with
+							| TCast(e1,_) when CastDetect.type_iseq gen e.etype e1.etype ->
+								e1
+							| _ -> e
+						in
+						expr_s w e; write w "->"; write_field w (field_name s)
+					| TField (e, s) ->
+						expr_s w e; write w "."; write_field w (field_name s)
+					| TTypeExpr mt ->
+						(match change_md mt with
+							| TClassDecl { cl_path = (["haxe"], "Int64") } -> write w ("global::" ^ module_s mt)
+							| TClassDecl { cl_path = (["haxe"], "Int32") } -> write w ("global::" ^ module_s mt)
+							| TClassDecl cl -> write w (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_params)));
+							| TEnumDecl en -> write w (t_s (TEnum(en, List.map (fun _ -> t_empty) en.e_params)))
+							| TTypeDecl td -> write w (t_s (gen.gfollow#run_f (TType(td, List.map (fun _ -> t_empty) td.t_params))))
+							| TAbstractDecl a -> write w (t_s (TAbstract(a, List.map (fun _ -> t_empty) a.a_params)))
+						)
+					| TParenthesis e ->
+						write w "("; expr_s w e; write w ")"
+					| TMeta (_,e) ->
+							expr_s w e
+					| TArrayDecl el
+					| TCall ({ eexpr = TLocal { v_name = "__array__" } }, el)
+					| TCall ({ eexpr = TField(_, FStatic({ cl_path = (["cs"],"NativeArray") }, { cf_name = "make" })) }, el) ->
+						let _, el = extract_tparams [] el in
+						print w "new %s" (t_s e.etype);
+						write w "{";
+						ignore (List.fold_left (fun acc e ->
+							(if acc <> 0 then write w ", ");
+							expr_s w e;
+							acc + 1
+						) 0 el);
+						write w "}"
+					| TCall ({ eexpr = TLocal { v_name = "__delegate__" } }, [del]) ->
+						expr_s w del
+					| TCall ({ eexpr = TLocal( { v_name = "__is__" } ) }, [ expr; { eexpr = TTypeExpr(md) } ] ) ->
+						write w "( ";
+						expr_s w expr;
+						write w " is ";
+						write w (md_s md);
+						write w " )"
+					| TCall ({ eexpr = TLocal( { v_name = "__as__" } ) }, [ expr; { eexpr = TTypeExpr(md) } ] ) ->
+						write w "( ";
+						expr_s w expr;
+						write w " as ";
+						write w (md_s md);
+						write w " )"
+					| TCall ({ eexpr = TLocal( { v_name = "__as__" } ) }, expr :: _ ) ->
+						write w "( ";
+						expr_s w expr;
+						write w " as ";
+						write w (t_s e.etype);
+						write w " )";
+					| TCall ({ eexpr = TLocal( { v_name = "__cs__" } ) }, [ { eexpr = TConst(TString(s)) } ] ) ->
+						write w s
+					| TCall ({ eexpr = TLocal( { v_name = "__cs__" } ) }, { eexpr = TConst(TString(s)) } :: tl ) ->
+						Codegen.interpolate_code gen.gcon s tl (write w) (expr_s w) e.epos
+					| TCall ({ eexpr = TLocal( { v_name = "__stackalloc__" } ) }, [ e ] ) ->
+						write w "stackalloc byte[";
 						expr_s w e;
-						acc + 1
-					) 0 el);
-					write w "}"
-				| TCall ({ eexpr = TLocal { v_name = "__delegate__" } }, [del]) ->
-					expr_s w del
-				| TCall ({ eexpr = TLocal( { v_name = "__is__" } ) }, [ expr; { eexpr = TTypeExpr(md) } ] ) ->
-					write w "( ";
-					expr_s w expr;
-					write w " is ";
-					write w (md_s md);
-					write w " )"
-				| TCall ({ eexpr = TLocal( { v_name = "__as__" } ) }, [ expr; { eexpr = TTypeExpr(md) } ] ) ->
-					write w "( ";
-					expr_s w expr;
-					write w " as ";
-					write w (md_s md);
-					write w " )"
-				| TCall ({ eexpr = TLocal( { v_name = "__as__" } ) }, expr :: _ ) ->
-					write w "( ";
-					expr_s w expr;
-					write w " as ";
-					write w (t_s e.etype);
-					write w " )";
-				| TCall ({ eexpr = TLocal( { v_name = "__cs__" } ) }, [ { eexpr = TConst(TString(s)) } ] ) ->
-					write w s
-				| TCall ({ eexpr = TLocal( { v_name = "__cs__" } ) }, { eexpr = TConst(TString(s)) } :: tl ) ->
-					Codegen.interpolate_code gen.gcon s tl (write w) (expr_s w) e.epos
-				| TCall ({ eexpr = TLocal( { v_name = "__stackalloc__" } ) }, [ e ] ) ->
-					write w "stackalloc byte[";
-					expr_s w e;
-					write w "]"
-				| TCall ({ eexpr = TLocal( { v_name = "__unsafe__" } ) }, [ e ] ) ->
-					write w "unsafe";
-					expr_s w (mk_block e)
-				| TCall ({ eexpr = TLocal( { v_name = "__checked__" } ) }, [ e ] ) ->
-					write w "checked";
-					expr_s w (mk_block e)
-				| TCall ({ eexpr = TLocal( { v_name = "__lock__" } ) }, [ eobj; eblock ] ) ->
-					write w "lock(";
-					expr_s w eobj;
-					write w ")";
-					expr_s w (mk_block eblock)
-				| TCall ({ eexpr = TLocal( { v_name = "__fixed__" } ) }, [ e ] ) ->
-					let fixeds = ref [] in
-					let rec loop = function
-						| ({ eexpr = TVar(v, Some(e) ) } as expr) :: tl when is_pointer gen v.v_type ->
-							let e = match get_ptr e with
-								| None -> e
-								| Some e -> e
-							in
-							fixeds := (v,e,expr) :: !fixeds;
-							loop tl;
-						| el when !fixeds <> [] ->
-							let rec loop fx acc = match fx with
-								| (v,e,expr) :: tl ->
-									write w "fixed(";
-									let vf = mk_temp "fixed" v.v_type in
-									expr_s w { expr with eexpr = TVar(vf, Some e) };
-									write w ") ";
-									begin_block w;
-									expr_s w { expr with eexpr = TVar(v, Some (mk_local vf expr.epos)) };
-									write w ";";
-									newline w;
-									loop tl (acc + 1)
-								| [] -> acc
-							in
-							let nblocks = loop (List.rev !fixeds) 0 in
-							in_value := false;
-							expr_s w { e with eexpr = TBlock el };
-							for i = 1 to nblocks do
-								end_block w
-							done
-						| _ ->
-							trace (debug_expr e);
-							gen.gcon.error "Invalid 'fixed' keyword format" e.epos
-					in
-					(match e.eexpr with
-						| TBlock bl -> loop bl
-						| _ ->
-							trace "not block";
-							trace (debug_expr e);
-							gen.gcon.error "Invalid 'fixed' keyword format" e.epos
-					)
-				| TCall ({ eexpr = TLocal( { v_name = "__addressOf__" } ) }, [ e ] ) ->
-					let e = ensure_local e "for addressOf" in
-					write w "&";
-					expr_s w e
-				| TCall ({ eexpr = TLocal( { v_name = "__valueOf__" } ) }, [ e ] ) ->
-					write w "*(";
-					expr_s w e;
-					write w ")"
-				| TCall ({ eexpr = TLocal( { v_name = "__goto__" } ) }, [ { eexpr = TConst(TInt v) } ] ) ->
-					print w "goto label%ld" v
-				| TCall ({ eexpr = TLocal( { v_name = "__label__" } ) }, [ { eexpr = TConst(TInt v) } ] ) ->
-					print w "label%ld: {}" v
-				| TCall ({ eexpr = TLocal( { v_name = "__rethrow__" } ) }, _) ->
-					write w "throw"
-				(* operator overloading handling *)
-				| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__get" })) }, [idx]) when not (is_hxgen (TClassDecl cl)) ->
-					expr_s w { e with eexpr = TArray(ef, idx) }
-				| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__set" })) }, [idx; v]) when not (is_hxgen (TClassDecl cl)) ->
-					expr_s w { e with eexpr = TBinop(Ast.OpAssign, { e with eexpr = TArray(ef, idx) }, v) }
-				| TCall({ eexpr = TField(ef, FStatic(_,cf)) }, el) when PMap.mem cf.cf_name binops_names ->
-					let _, elr = extract_tparams [] el in
-					(match elr with
-					| [e1;e2] ->
-						expr_s w { e with eexpr = TBinop(PMap.find cf.cf_name binops_names, e1, e2) }
-					| _ -> do_call w e el)
-				| TCall({ eexpr = TField(ef, FStatic(_,cf)) }, el) when PMap.mem cf.cf_name unops_names ->
-					(match extract_tparams [] el with
-					| _, [e1] ->
-						expr_s w { e with eexpr = TUnop(PMap.find cf.cf_name unops_names, Ast.Prefix,e1) }
-					| _ -> do_call w e el)
-				| TCall (e, el) ->
-					do_call w e el
-				| TNew (({ cl_path = (["cs"], "NativeArray") } as cl), params, [ size ]) ->
-					let rec check_t_s t times =
-						match real_type t with
-							| TInst({ cl_path = (["cs"], "NativeArray") }, [param]) ->
-								(check_t_s param (times+1))
-							| _ ->
-								print w "new %s[" (t_s (run_follow gen t));
-								expr_s w size;
-								print w "]";
-								let rec loop i =
-									if i <= 0 then () else (write w "[]"; loop (i-1))
+						write w "]"
+					| TCall ({ eexpr = TLocal( { v_name = "__unsafe__" } ) }, [ e ] ) ->
+						write w "unsafe";
+						expr_s w (mk_block e)
+					| TCall ({ eexpr = TLocal( { v_name = "__checked__" } ) }, [ e ] ) ->
+						write w "checked";
+						expr_s w (mk_block e)
+					| TCall ({ eexpr = TLocal( { v_name = "__lock__" } ) }, [ eobj; eblock ] ) ->
+						write w "lock(";
+						expr_s w eobj;
+						write w ")";
+						expr_s w (mk_block eblock)
+					| TCall ({ eexpr = TLocal( { v_name = "__fixed__" } ) }, [ e ] ) ->
+						let fixeds = ref [] in
+						let rec loop = function
+							| ({ eexpr = TVar(v, Some(e) ) } as expr) :: tl when is_pointer gen v.v_type ->
+								let e = match get_ptr e with
+									| None -> e
+									| Some e -> e
 								in
-								loop (times - 1)
-					in
-					check_t_s (TInst(cl, params)) 0
-				| TNew ({ cl_path = ([], "String") } as cl, [], el) ->
-					write w "new ";
-					write w (t_s (TInst(cl, [])));
-					write w "(";
-					ignore (List.fold_left (fun acc e ->
-						(if acc <> 0 then write w ", ");
-						expr_s w e;
-						acc + 1
-					) 0 el);
-					write w ")"
-				| TNew ({ cl_kind = KTypeParameter _ } as cl, params, el) ->
-					print w "default(%s) /* This code should never be reached. It was produced by the use of @:generic on a new type parameter instance: %s */" (t_s (TInst(cl,params))) (path_param_s (TClassDecl cl) cl.cl_path params)
-				| TNew (cl, params, el) ->
-					write w "new ";
-					write w (path_param_s (TClassDecl cl) cl.cl_path params);
-					write w "(";
-					ignore (List.fold_left (fun acc e ->
-						(if acc <> 0 then write w ", ");
+								fixeds := (v,e,expr) :: !fixeds;
+								loop tl;
+							| el when !fixeds <> [] ->
+								let rec loop fx acc = match fx with
+									| (v,e,expr) :: tl ->
+										write w "fixed(";
+										let vf = mk_temp "fixed" v.v_type in
+										expr_s w { expr with eexpr = TVar(vf, Some e) };
+										write w ") ";
+										begin_block w;
+										expr_s w { expr with eexpr = TVar(v, Some (mk_local vf expr.epos)) };
+										write w ";";
+										newline w;
+										loop tl (acc + 1)
+									| [] -> acc
+								in
+								let nblocks = loop (List.rev !fixeds) 0 in
+								in_value := false;
+								expr_s w { e with eexpr = TBlock el };
+								for i = 1 to nblocks do
+									end_block w
+								done
+							| _ ->
+								trace (debug_expr e);
+								gen.gcon.error "Invalid 'fixed' keyword format" e.epos
+						in
+						(match e.eexpr with
+							| TBlock bl -> loop bl
+							| _ ->
+								trace "not block";
+								trace (debug_expr e);
+								gen.gcon.error "Invalid 'fixed' keyword format" e.epos
+						)
+					| TCall ({ eexpr = TLocal( { v_name = "__addressOf__" } ) }, [ e ] ) ->
+						let e = ensure_local e "for addressOf" in
+						write w "&";
+						expr_s w e
+					| TCall ({ eexpr = TLocal( { v_name = "__valueOf__" } ) }, [ e ] ) ->
+						write w "*(";
 						expr_s w e;
-						acc + 1
-					) 0 el);
-					write w ")"
-				| TUnop ((Ast.Increment as op), flag, e)
-				| TUnop ((Ast.Decrement as op), flag, e) ->
-					(match flag with
-						| Ast.Prefix -> write w ( " " ^ (Ast.s_unop op) ^ " " ); expr_s w e
-						| Ast.Postfix -> expr_s w e; write w (Ast.s_unop op))
-				| TUnop (op, flag, e) ->
-					(match flag with
-						| Ast.Prefix -> write w ( " " ^ (Ast.s_unop op) ^ " (" ); expr_s w e; write w ") "
-						| Ast.Postfix -> write w "("; expr_s w e; write w (") " ^ Ast.s_unop op))
-				| TVar (var, eopt) ->
-					print w "%s " (t_s var.v_type);
-					write_id w var.v_name;
-					(match eopt with
-						| None ->
-							write w " = ";
-							expr_s w (null var.v_type e.epos)
-						| Some e ->
-							write w " = ";
-							expr_s w e
-					)
-				| TBlock [e] when was_in_value ->
-					expr_s w e
-				| TBlock el ->
-					begin_block w;
-					List.iter (fun e ->
+						write w ")"
+					| TCall ({ eexpr = TLocal( { v_name = "__goto__" } ) }, [ { eexpr = TConst(TInt v) } ] ) ->
+						print w "goto label%ld" v
+					| TCall ({ eexpr = TLocal( { v_name = "__label__" } ) }, [ { eexpr = TConst(TInt v) } ] ) ->
+						print w "label%ld: {}" v
+					| TCall ({ eexpr = TLocal( { v_name = "__rethrow__" } ) }, _) ->
+						write w "throw"
+					(* operator overloading handling *)
+					| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__get" })) }, [idx]) when not (is_hxgen (TClassDecl cl)) ->
+						expr_s w { e with eexpr = TArray(ef, idx) }
+					| TCall({ eexpr = TField(ef, FInstance(cl,_,{ cf_name = "__set" })) }, [idx; v]) when not (is_hxgen (TClassDecl cl)) ->
+						expr_s w { e with eexpr = TBinop(Ast.OpAssign, { e with eexpr = TArray(ef, idx) }, v) }
+					| TCall({ eexpr = TField(ef, FStatic(_,cf)) }, el) when PMap.mem cf.cf_name binops_names ->
+						let _, elr = extract_tparams [] el in
+						(match elr with
+						| [e1;e2] ->
+							expr_s w { e with eexpr = TBinop(PMap.find cf.cf_name binops_names, e1, e2) }
+						| _ -> do_call w e el)
+					| TCall({ eexpr = TField(ef, FStatic(_,cf)) }, el) when PMap.mem cf.cf_name unops_names ->
+						(match extract_tparams [] el with
+						| _, [e1] ->
+							expr_s w { e with eexpr = TUnop(PMap.find cf.cf_name unops_names, Ast.Prefix,e1) }
+						| _ -> do_call w e el)
+					| TCall (e, el) ->
+						do_call w e el
+					| TNew (({ cl_path = (["cs"], "NativeArray") } as cl), params, [ size ]) ->
+						let rec check_t_s t times =
+							match real_type t with
+								| TInst({ cl_path = (["cs"], "NativeArray") }, [param]) ->
+									(check_t_s param (times+1))
+								| _ ->
+									print w "new %s[" (t_s (run_follow gen t));
+									expr_s w size;
+									print w "]";
+									let rec loop i =
+										if i <= 0 then () else (write w "[]"; loop (i-1))
+									in
+									loop (times - 1)
+						in
+						check_t_s (TInst(cl, params)) 0
+					| TNew ({ cl_path = ([], "String") } as cl, [], el) ->
+						write w "new ";
+						write w (t_s (TInst(cl, [])));
+						write w "(";
+						ignore (List.fold_left (fun acc e ->
+							(if acc <> 0 then write w ", ");
+							expr_s w e;
+							acc + 1
+						) 0 el);
+						write w ")"
+					| TNew ({ cl_kind = KTypeParameter _ } as cl, params, el) ->
+						print w "default(%s) /* This code should never be reached. It was produced by the use of @:generic on a new type parameter instance: %s */" (t_s (TInst(cl,params))) (path_param_s (TClassDecl cl) cl.cl_path params)
+					| TNew (cl, params, el) ->
+						write w "new ";
+						write w (path_param_s (TClassDecl cl) cl.cl_path params);
+						write w "(";
+						ignore (List.fold_left (fun acc e ->
+							(if acc <> 0 then write w ", ");
+							expr_s w e;
+							acc + 1
+						) 0 el);
+						write w ")"
+					| TUnop ((Ast.Increment as op), flag, e)
+					| TUnop ((Ast.Decrement as op), flag, e) ->
+						(match flag with
+							| Ast.Prefix -> write w ( " " ^ (Ast.s_unop op) ^ " " ); expr_s w e
+							| Ast.Postfix -> expr_s w e; write w (Ast.s_unop op))
+					| TUnop (op, flag, e) ->
+						(match flag with
+							| Ast.Prefix -> write w ( " " ^ (Ast.s_unop op) ^ " (" ); expr_s w e; write w ") "
+							| Ast.Postfix -> write w "("; expr_s w e; write w (") " ^ Ast.s_unop op))
+					| TVar (var, eopt) ->
+						print w "%s " (t_s var.v_type);
+						write_id w var.v_name;
+						(match eopt with
+							| None ->
+								write w " = ";
+								expr_s w (null var.v_type e.epos)
+							| Some e ->
+								write w " = ";
+								expr_s w e
+						)
+					| TBlock [e] when was_in_value ->
+						expr_s w e
+					| TBlock el ->
+						begin_block w;
 						List.iter (fun e ->
-							line_directive w e.epos;
+							List.iter (fun e ->
+								line_directive w e.epos;
+								in_value := false;
+								expr_s w e;
+								(if has_semicolon e then write w ";");
+								newline w
+							) (extract_statements e)
+						) el;
+						end_block w
+					| TIf (econd, e1, Some(eelse)) when was_in_value ->
+						let base = t_s e.etype in
+						write w "( ";
+						expr_s w (mk_paren econd);
+						write w " ? ";
+						if t_s e1.etype <> base then
+							expr_s w (mk_cast e.etype e1)
+						else
+							expr_s w (mk_paren e1);
+
+						write w " : ";
+						if t_s eelse.etype <> base then
+							expr_s w (mk_cast e.etype eelse)
+						else
+							expr_s w (mk_paren eelse);
+						write w " )";
+					| TIf (econd, e1, eelse) ->
+						write w "if ";
+						expr_s w (mk_paren econd);
+						write w " ";
+						in_value := false;
+						expr_s w (mk_block e1);
+						(match eelse with
+							| None -> ()
+							| Some e ->
+								write w "else ";
+								in_value := false;
+								let e = match e.eexpr with
+									| TIf _ -> e
+									| TBlock [{eexpr = TIf _} as e] -> e
+									| _ -> mk_block e
+								in
+								expr_s w e
+						)
+					| TWhile (econd, eblock, flag) ->
+						(match flag with
+							| Ast.NormalWhile ->
+								write w "while ";
+								expr_s w (mk_paren econd);
+								write w " ";
+								in_value := false;
+								expr_s w (mk_block eblock)
+							| Ast.DoWhile ->
+								write w "do ";
+								in_value := false;
+								expr_s w (mk_block eblock);
+								write w "while ";
+								in_value := true;
+								expr_s w (mk_paren econd);
+						)
+					| TSwitch (econd, ele_l, default) ->
+						write w "switch ";
+						expr_s w (mk_paren econd);
+						write w " ";
+						begin_block w;
+						List.iter (fun (el, e) ->
+							List.iter (fun e ->
+								write w "case ";
+								in_value := true;
+								expr_s w e;
+								write w ":";
+								newline w;
+							) el;
 							in_value := false;
-							expr_s w e;
-							(if has_semicolon e then write w ";");
+							expr_s w (mk_block e);
+							newline w;
 							newline w
-						) (extract_statements e)
-					) el;
-					end_block w
-				| TIf (econd, e1, Some(eelse)) when was_in_value ->
-					let base = t_s e.etype in
-					write w "( ";
-					expr_s w (mk_paren econd);
-					write w " ? ";
-					if t_s e1.etype <> base then
-						expr_s w (mk_cast e.etype e1)
-					else
-						expr_s w (mk_paren e1);
-
-					write w " : ";
-					if t_s eelse.etype <> base then
-						expr_s w (mk_cast e.etype eelse)
-					else
-						expr_s w (mk_paren eelse);
-					write w " )";
-				| TIf (econd, e1, eelse) ->
-					write w "if ";
-					expr_s w (mk_paren econd);
-					write w " ";
-					in_value := false;
-					expr_s w (mk_block e1);
-					(match eelse with
-						| None -> ()
-						| Some e ->
-							write w "else ";
-							in_value := false;
-							let e = match e.eexpr with
-								| TIf _ -> e
-								| TBlock [{eexpr = TIf _} as e] -> e
-								| _ -> mk_block e
-							in
-							expr_s w e
-					)
-				| TWhile (econd, eblock, flag) ->
-					(match flag with
-						| Ast.NormalWhile ->
-							write w "while ";
-							expr_s w (mk_paren econd);
-							write w " ";
-							in_value := false;
-							expr_s w (mk_block eblock)
-						| Ast.DoWhile ->
-							write w "do ";
+						) ele_l;
+						if is_some default then begin
+							write w "default:";
+							newline w;
 							in_value := false;
-							expr_s w (mk_block eblock);
-							write w "while ";
-							in_value := true;
-							expr_s w (mk_paren econd);
-					)
-				| TSwitch (econd, ele_l, default) ->
-					write w "switch ";
-					expr_s w (mk_paren econd);
-					write w " ";
-					begin_block w;
-					List.iter (fun (el, e) ->
-						List.iter (fun e ->
-							write w "case ";
-							in_value := true;
-							expr_s w e;
-							write w ":";
+							expr_s w (get default);
 							newline w;
-						) el;
-						in_value := false;
-						expr_s w (mk_block e);
-						newline w;
-						newline w
-					) ele_l;
-					if is_some default then begin
-						write w "default:";
-						newline w;
-						in_value := false;
-						expr_s w (get default);
-						newline w;
-					end;
-					end_block w
-				| TTry (tryexpr, ve_l) ->
-					write w "try ";
-					in_value := false;
-					expr_s w (mk_block tryexpr);
-					List.iter (fun (var, e) ->
-						print w "catch (%s %s)" (t_s var.v_type) (var.v_name);
+						end;
+						end_block w
+					| TTry (tryexpr, ve_l) ->
+						write w "try ";
 						in_value := false;
-						expr_s w (mk_block e);
-						newline w
-					) ve_l
-				| TReturn eopt ->
-					write w "return";
-					if is_some eopt then (write w " "; expr_s w (get eopt))
-				| TBreak -> write w "break"
-				| TContinue -> write w "continue"
-				| TThrow e ->
-					write w "throw ";
-					expr_s w e
-				| TCast (e1,md_t) ->
-					((*match gen.gfollow#run_f e.etype with
-						| TType({ t_path = ([], "UInt") }, []) ->
-							write w "( unchecked ((uint) ";
-							expr_s w e1;
-							write w ") )"
-						| _ ->*)
-							(* FIXME I'm ignoring module type *)
-							print w "((%s) (" (t_s e.etype);
-							expr_s w e1;
-							write w ") )"
-					)
-				| TFor (_,_,content) ->
-					write w "[ for not supported ";
-					expr_s w content;
-					write w " ]";
-					if !strict_mode then assert false
-				| TObjectDecl _ -> write w "[ obj decl not supported ]"; if !strict_mode then assert false
-				| TFunction _ -> write w "[ func decl not supported ]"; if !strict_mode then assert false
-				| TEnumParameter _ -> write w "[ enum parameter not supported ]"; if !strict_mode then assert false
-		)
-		and do_call w e el =
-			let params, el = extract_tparams [] el in
-			let params = List.rev params in
-
-			expr_s w e;
-
-			(match params with
-				| _ :: _ when not (erase_generics && field_is_hxgeneric e) ->
-					let md = match e.eexpr with
-						| TField(ef, _) ->
-							t_to_md (run_follow gen ef.etype)
-						| _ -> assert false
-					in
-					write w "<";
-					ignore (List.fold_left (fun acc t ->
-						(if acc <> 0 then write w ", ");
-						write w (t_s t);
-						acc + 1
-					) 0 (change_param_type md params));
-					write w ">"
-				| _ -> ()
-			);
-
-			let rec loop acc elist tlist =
-				match elist, tlist with
-					| e :: etl, (_,_,t) :: ttl ->
-						(if acc <> 0 then write w ", ");
-						(match real_type t with
-							| TType({ t_path = (["cs"], "Ref") }, _)
-							| TAbstract ({ a_path = (["cs"], "Ref") },_) ->
-								let e = ensure_refout e "of type cs.Ref" in
-								write w "ref ";
-								expr_s w e
-							| TType({ t_path = (["cs"], "Out") }, _)
-							| TAbstract ({ a_path = (["cs"], "Out") },_) ->
-								let e = ensure_refout e "of type cs.Out" in
-								write w "out ";
-								expr_s w e
-							| _ ->
-								expr_s w e
-						);
-						loop (acc + 1) etl ttl
-					| e :: etl, [] ->
-						(if acc <> 0 then write w ", ");
-						expr_s w e;
-						loop (acc + 1) etl []
+						expr_s w (mk_block tryexpr);
+						List.iter (fun (var, e) ->
+							print w "catch (%s %s)" (t_s var.v_type) (var.v_name);
+							in_value := false;
+							expr_s w (mk_block e);
+							newline w
+						) ve_l
+					| TReturn eopt ->
+						write w "return";
+						if is_some eopt then (write w " "; expr_s w (get eopt))
+					| TBreak -> write w "break"
+					| TContinue -> write w "continue"
+					| TThrow e ->
+						write w "throw ";
+						expr_s w e
+					| TCast (e1,md_t) ->
+						((*match gen.gfollow#run_f e.etype with
+							| TType({ t_path = ([], "UInt") }, []) ->
+								write w "( unchecked ((uint) ";
+								expr_s w e1;
+								write w ") )"
+							| _ ->*)
+								(* FIXME I'm ignoring module type *)
+								print w "((%s) (" (t_s e.etype);
+								expr_s w e1;
+								write w ") )"
+						)
+					| TFor (_,_,content) ->
+						write w "[ for not supported ";
+						expr_s w content;
+						write w " ]";
+						if !strict_mode then assert false
+					| TObjectDecl _ -> write w "[ obj decl not supported ]"; if !strict_mode then assert false
+					| TFunction _ -> write w "[ func decl not supported ]"; if !strict_mode then assert false
+					| TEnumParameter _ -> write w "[ enum parameter not supported ]"; if !strict_mode then assert false
+			)
+			and do_call w e el =
+				let params, el = extract_tparams [] el in
+				let params = List.rev params in
+
+				expr_s w e;
+
+				(match params with
+					| _ :: _ when not (erase_generics && field_is_hxgeneric e) ->
+						let md = match e.eexpr with
+							| TField(ef, _) ->
+								t_to_md (run_follow gen ef.etype)
+							| _ -> assert false
+						in
+						write w "<";
+						ignore (List.fold_left (fun acc t ->
+							(if acc <> 0 then write w ", ");
+							write w (t_s t);
+							acc + 1
+						) 0 (change_param_type md params));
+						write w ">"
 					| _ -> ()
-			in
-			write w "(";
-			let ft = match follow e.etype with
-				| TFun(args,_) -> args
-				| _ -> []
-			in
+				);
+
+				let rec loop acc elist tlist =
+					match elist, tlist with
+						| e :: etl, (_,_,t) :: ttl ->
+							(if acc <> 0 then write w ", ");
+							(match real_type t with
+								| TType({ t_path = (["cs"], "Ref") }, _)
+								| TAbstract ({ a_path = (["cs"], "Ref") },_) ->
+									let e = ensure_refout e "of type cs.Ref" in
+									write w "ref ";
+									expr_s w e
+								| TType({ t_path = (["cs"], "Out") }, _)
+								| TAbstract ({ a_path = (["cs"], "Out") },_) ->
+									let e = ensure_refout e "of type cs.Out" in
+									write w "out ";
+									expr_s w e
+								| _ ->
+									expr_s w e
+							);
+							loop (acc + 1) etl ttl
+						| e :: etl, [] ->
+							(if acc <> 0 then write w ", ");
+							expr_s w e;
+							loop (acc + 1) etl []
+						| _ -> ()
+				in
+				write w "(";
+				let ft = match follow e.etype with
+					| TFun(args,_) -> args
+					| _ -> []
+				in
 
-			loop 0 el ft;
+				loop 0 el ft;
 
-			write w ")"
+				write w ")"
+			in
+			expr_s w e
 		in
-		expr_s w e
-	in
-
-	let rec gen_fpart_attrib w = function
-		| EConst( Ident i ), _ ->
-			write w i
-		| EField( ef, f ), _ ->
-			gen_fpart_attrib w ef;
-			write w ".";
-			write w f
-		| _, p ->
-			gen.gcon.error "Invalid expression inside @:meta metadata" p
-	in
 
-	let rec gen_spart w = function
-		| EConst c, p -> (match c with
-			| Int s | Float s | Ident s ->
-				write w s
-			| String s ->
-				write w "\"";
-				write w (escape s);
-				write w "\""
-			| _ -> gen.gcon.error "Invalid expression inside @:meta metadata" p)
-		| EField( ef, f ), _ ->
-			gen_spart w ef;
-			write w ".";
-			write w f
-		| EBinop( Ast.OpAssign, (EConst (Ident s), _), e2 ), _ ->
-			write w s;
-			write w " = ";
-			gen_spart w e2
-		| EArrayDecl( el ), _ ->
-			write w "new[] {";
-			let fst = ref true in
-			List.iter (fun e ->
-				if !fst then fst := false else write w ", ";
-				gen_spart w e
-			) el;
-			write w "}"
-		| ECall(fpart,args), _ ->
-			gen_fpart_attrib w fpart;
-			write w "(";
-			let fst = ref true in
-			List.iter (fun e ->
-				if !fst then fst := false else write w ", ";
-				gen_spart w e
-			) args;
-			write w ")"
-		| _, p ->
-			gen.gcon.error "Invalid expression inside @:meta metadata" p
-	in
+		let rec gen_fpart_attrib w = function
+			| EConst( Ident i ), _ ->
+				write w i
+			| EField( ef, f ), _ ->
+				gen_fpart_attrib w ef;
+				write w ".";
+				write w f
+			| _, p ->
+				gen.gcon.error "Invalid expression inside @:meta metadata" p
+		in
 
-	let gen_attributes w metadata =
-		List.iter (function
-			| Meta.Meta, [EConst(String s), _], _ ->
-				write w "[";
+		let rec gen_spart w = function
+			| EConst c, p -> (match c with
+				| Int s | Float s | Ident s ->
+					write w s
+				| String s ->
+					write w "\"";
+					write w (escape s);
+					write w "\""
+				| _ -> gen.gcon.error "Invalid expression inside @:meta metadata" p)
+			| EField( ef, f ), _ ->
+				gen_spart w ef;
+				write w ".";
+				write w f
+			| EBinop( Ast.OpAssign, (EConst (Ident s), _), e2 ), _ ->
 				write w s;
-				write w "]";
-				newline w
-			| Meta.Meta, [meta], _ ->
-				write w "[";
-				gen_spart w meta;
-				write w "]";
-				newline w
-			| _ -> ()
-		) metadata
-	in
-
-	let gen_nocompletion w metadata =
-		if Meta.has Meta.NoCompletion metadata then begin
-			write w "[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]";
-			newline w
-		end;
-	in
+				write w " = ";
+				gen_spart w e2
+			| EArrayDecl( el ), _ ->
+				write w "new[] {";
+				let fst = ref true in
+				List.iter (fun e ->
+					if !fst then fst := false else write w ", ";
+					gen_spart w e
+				) el;
+				write w "}"
+			| ECall(fpart,args), _ ->
+				gen_fpart_attrib w fpart;
+				write w "(";
+				let fst = ref true in
+				List.iter (fun e ->
+					if !fst then fst := false else write w ", ";
+					gen_spart w e
+				) args;
+				write w ")"
+			| _, p ->
+				gen.gcon.error "Invalid expression inside @:meta metadata" p
+		in
 
-	let argt_s t =
-		let w = new_source_writer () in
-		let rec run t =
-			match t with
-				| TType (tdef,p) ->
-					gen_attributes w tdef.t_meta;
-					run (follow_once t)
-				| TMono r ->
-					(match !r with
-					| Some t -> run t
-					| _ -> () (* avoid infinite loop / should be the same in this context *))
-				| TLazy f ->
-					run (!f())
+		let gen_attributes w metadata =
+			List.iter (function
+				| Meta.Meta, [EConst(String s), _], _ ->
+					write w "[";
+					write w s;
+					write w "]";
+					newline w
+				| Meta.Meta, [meta], _ ->
+					write w "[";
+					gen_spart w meta;
+					write w "]";
+					newline w
 				| _ -> ()
+			) metadata
 		in
-		run t;
-		let ret = match run_follow gen t with
-			| TType ({ t_path = (["cs"], "Ref") }, [t])
-			| TAbstract ({ a_path = (["cs"], "Ref") },[t]) -> "ref " ^ t_s t
-			| TType ({ t_path = (["cs"], "Out") }, [t])
-			| TAbstract ({ a_path = (["cs"], "Out") },[t]) -> "out " ^ t_s t
-			| t -> t_s t
-		in
-		let c = contents w in
-		if c <> "" then
-			c ^ " " ^ ret
-		else
-			ret
-	in
-
-	let get_string_params cl cl_params =
-		let hxgen = is_hxgen (TClassDecl cl) in
-		match cl_params with
-			| (_ :: _) when not (erase_generics && is_hxgeneric (TClassDecl cl)) ->
-				let get_param_name t = match follow t with TInst(cl, _) -> snd cl.cl_path | _ -> assert false in
-				let params = sprintf "<%s>" (String.concat ", " (List.map (fun (_, tcl) -> get_param_name tcl) cl_params)) in
-				let params_extends =
-					if hxgen
-					(* this is temprorary, see https://github.com/HaxeFoundation/haxe/issues/3526 *)
-					|| not (Meta.has (Meta.Custom ":nativeTypeConstraints") cl.cl_meta)
-					then
-						[""]
-					else
-						List.fold_left (fun acc (name, t) ->
-							match run_follow gen t with
-								| TInst({cl_kind = KTypeParameter constraints}, _) when constraints <> [] ->
-									(* base class should come before interface constraints *)
-									let base_class_constraints = ref [] in
-									let other_constraints = List.fold_left (fun acc t ->
-										match follow t with
-											(* string is implicitly sealed, maybe haxe should have it final as well *)
-											| TInst ({ cl_path=[],"String" }, []) ->
-												acc
-
-											(* non-sealed class *)
-											| TInst ({ cl_interface = false; cl_meta = meta},_) when not (Meta.has Meta.Final meta) ->
-												base_class_constraints := (t_s t) :: !base_class_constraints;
-												acc;
-
-											(* interface *)
-											| TInst ({ cl_interface = true}, _) ->
-												(t_s t) :: acc
-
-											(* skip anything other *)
-											| _ ->
-												acc
-									) [] constraints in
-
-									let s_constraints = (!base_class_constraints @ other_constraints) in
-									if s_constraints <> [] then
-										(sprintf " where %s : %s" (get_param_name t) (String.concat ", " s_constraints) :: acc)
-									else
-										acc;
-								| _ -> acc
-						) [] cl_params in
-				(params, String.concat " " params_extends)
-			| _ -> ("","")
-	in
-
-	let gen_field_decl w visibility v_n modifiers t n =
-		let parts = ref [] in
-		if visibility <> "" then parts := visibility :: !parts;
-		if v_n <> "" then parts := v_n :: !parts;
-		if modifiers <> [] then parts := modifiers @ !parts;
-		if t <> "" then parts := t :: !parts;
-		parts := n :: !parts;
-		write w (String.concat " " (List.rev !parts));
-	in
 
-	let rec gen_event w is_static cl (event,t,custom,add,remove) =
-		let is_interface = cl.cl_interface in
-		let visibility = if is_interface then "" else "public" in
-		let visibility, modifiers = get_fun_modifiers event.cf_meta visibility ["event"] in
-		let v_n = if is_static then "static" else "" in
-		gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_field event.cf_name);
-		if custom && not is_interface then begin
-			write w " ";
-			begin_block w;
-			print w "add { _add_%s(value); }" event.cf_name;
-			newline w;
-			print w "remove { _remove_%s(value); }" event.cf_name;
-			newline w;
-			end_block w;
-			newline w;
-		end else
-			write w ";\n";
-		newline w;
-	in
+		let gen_nocompletion w metadata =
+			if Meta.has Meta.NoCompletion metadata then begin
+				write w "[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]";
+				newline w
+			end;
+		in
 
-	let rec gen_prop w is_static cl is_final (prop,t,get,set) =
-		gen_attributes w prop.cf_meta;
-		let is_interface = cl.cl_interface in
-		let fn_is_final = function
-			| None -> true
-			| Some ({ cf_kind = Method mkind } as m) ->
-				(match mkind with | MethInline -> true | _ -> false) || Meta.has Meta.Final m.cf_meta
-			| _ -> assert false
+		let argt_s t =
+			let w = new_source_writer () in
+			let rec run t =
+				match t with
+					| TType (tdef,p) ->
+						gen_attributes w tdef.t_meta;
+						run (follow_once t)
+					| TMono r ->
+						(match !r with
+						| Some t -> run t
+						| _ -> () (* avoid infinite loop / should be the same in this context *))
+					| TLazy f ->
+						run (!f())
+					| _ -> ()
+			in
+			run t;
+			let ret = match run_follow gen t with
+				| TType ({ t_path = (["cs"], "Ref") }, [t])
+				| TAbstract ({ a_path = (["cs"], "Ref") },[t]) -> "ref " ^ t_s t
+				| TType ({ t_path = (["cs"], "Out") }, [t])
+				| TAbstract ({ a_path = (["cs"], "Out") },[t]) -> "out " ^ t_s t
+				| t -> t_s t
+			in
+			let c = contents w in
+			if c <> "" then
+				c ^ " " ^ ret
+			else
+				ret
 		in
-		let is_virtual = not (is_interface || is_final || Meta.has Meta.Final prop.cf_meta || fn_is_final get || fn_is_final set) in
 
-		let fn_is_override = function
-			| Some cf -> List.memq cf cl.cl_overrides
-			| None -> false
+		let get_string_params cl cl_params =
+			let hxgen = is_hxgen (TClassDecl cl) in
+			match cl_params with
+				| (_ :: _) when not (erase_generics && is_hxgeneric (TClassDecl cl)) ->
+					let get_param_name t = match follow t with TInst(cl, _) -> snd cl.cl_path | _ -> assert false in
+					let params = sprintf "<%s>" (String.concat ", " (List.map (fun (_, tcl) -> get_param_name tcl) cl_params)) in
+					let params_extends =
+						if hxgen
+						(* this is temprorary, see https://github.com/HaxeFoundation/haxe/issues/3526 *)
+						|| not (Meta.has (Meta.Custom ":nativeTypeConstraints") cl.cl_meta)
+						then
+							[""]
+						else
+							List.fold_left (fun acc (name, t) ->
+								match run_follow gen t with
+									| TInst({cl_kind = KTypeParameter constraints}, _) when constraints <> [] ->
+										(* base class should come before interface constraints *)
+										let base_class_constraints = ref [] in
+										let other_constraints = List.fold_left (fun acc t ->
+											match follow t with
+												(* string is implicitly sealed, maybe haxe should have it final as well *)
+												| TInst ({ cl_path=[],"String" }, []) ->
+													acc
+
+												(* non-sealed class *)
+												| TInst ({ cl_interface = false; cl_meta = meta},_) when not (Meta.has Meta.Final meta) ->
+													base_class_constraints := (t_s t) :: !base_class_constraints;
+													acc;
+
+												(* interface *)
+												| TInst ({ cl_interface = true}, _) ->
+													(t_s t) :: acc
+
+												(* skip anything other *)
+												| _ ->
+													acc
+										) [] constraints in
+
+										let s_constraints = (!base_class_constraints @ other_constraints) in
+										if s_constraints <> [] then
+											(sprintf " where %s : %s" (get_param_name t) (String.concat ", " s_constraints) :: acc)
+										else
+											acc;
+									| _ -> acc
+							) [] cl_params in
+					(params, String.concat " " params_extends)
+				| _ -> ("","")
 		in
-		let is_override = fn_is_override get || fn_is_override set in
-		let visibility = if is_interface then "" else "public" in
-		let visibility, modifiers = get_fun_modifiers prop.cf_meta visibility [] in
-		let v_n = if is_static then "static" else if is_override && not is_interface then "override" else if is_virtual then "virtual" else "" in
-		gen_nocompletion w prop.cf_meta;
-
-		gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_field prop.cf_name);
-
-		let check cf = match cf with
-			| Some ({ cf_overloads = o :: _ } as cf) ->
-					gen.gcon.error "Property functions with more than one overload is currently unsupported" cf.cf_pos;
-					gen.gcon.error "Property functions with more than one overload is currently unsupported" o.cf_pos
-			| _ -> ()
+
+		let gen_field_decl w visibility v_n modifiers t n =
+			let parts = ref [] in
+			if visibility <> "" then parts := visibility :: !parts;
+			if v_n <> "" then parts := v_n :: !parts;
+			if modifiers <> [] then parts := modifiers @ !parts;
+			if t <> "" then parts := t :: !parts;
+			parts := n :: !parts;
+			write w (String.concat " " (List.rev !parts));
 		in
-		check get;
-		check set;
-
-		write w " ";
-		if is_interface then begin
-			write w "{ ";
-			let s = ref "" in
-			(match prop.cf_kind with Var { v_read = AccCall } -> write w "get;"; s := " "; | _ -> ());
-			(match prop.cf_kind with Var { v_write = AccCall } -> print w "%sset;" !s | _ -> ());
-			write w " }";
-			newline w;
-		end else begin
-			begin_block w;
-			(match get with
-				| Some cf ->
-					print w "get { return _get_%s(); }" prop.cf_name;
-					newline w;
-					cf.cf_meta <- (Meta.Custom "?prop_impl", [], null_pos) :: cf.cf_meta;
-				| None -> ());
-			(match set with
-				| Some cf ->
-					print w "set { _set_%s(value); }" prop.cf_name;
-					newline w;
-					cf.cf_meta <- (Meta.Custom "?prop_impl", [], null_pos) :: cf.cf_meta;
-				| None -> ());
-			end_block w;
-			newline w;
+
+		let rec gen_event w is_static cl (event,t,custom,add,remove) =
+			let is_interface = cl.cl_interface in
+			let visibility = if is_interface then "" else "public" in
+			let visibility, modifiers = get_fun_modifiers event.cf_meta visibility ["event"] in
+			let v_n = if is_static then "static" else "" in
+			gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_field event.cf_name);
+			if custom && not is_interface then begin
+				write w " ";
+				begin_block w;
+				print w "add { _add_%s(value); }" event.cf_name;
+				newline w;
+				print w "remove { _remove_%s(value); }" event.cf_name;
+				newline w;
+				end_block w;
+				newline w;
+			end else
+				write w ";\n";
 			newline w;
-		end;
-	in
+		in
 
-	let needs_unchecked e =
-		let rec loop e = match e.eexpr with
-		(* a non-zero integer constant means that we want unchecked context *)
-		| TConst (TInt i) when i <> Int32.zero ->
-			raise Exit
-
-		(* don't recurse into explicit checked blocks *)
-		| TCall ({ eexpr = TLocal({ v_name = "__checked__" }) }, _) ->
-			()
-
-		(* skip reflection field hashes as they are safe *)
-		| TNew ({ cl_path = (["haxe"; "lang"],"DynamicObject") }, [], [_; e1; _; e2]) ->
-			loop e1;
-			loop e2
-		| TNew ({ cl_path = (["haxe"; "lang"],"Closure") }, [], [eo; _; _]) ->
-			loop eo
-		| TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["haxe"; "lang"],"Runtime" },
-				 { cf_name = "getField" | "setField" | "getField_f" | "setField_f" | "callField" })) },
-				 eo :: _ :: _ :: rest) ->
-			loop eo;
-			List.iter loop rest
+		let rec gen_prop w is_static cl is_final (prop,t,get,set) =
+			gen_attributes w prop.cf_meta;
+			let is_interface = cl.cl_interface in
+			let fn_is_final = function
+				| None -> true
+				| Some ({ cf_kind = Method mkind } as m) ->
+					(match mkind with | MethInline -> true | _ -> false) || Meta.has Meta.Final m.cf_meta
+				| _ -> assert false
+			in
+			let is_virtual = not (is_interface || is_final || Meta.has Meta.Final prop.cf_meta || fn_is_final get || fn_is_final set) in
 
-		| _ ->
-			Type.iter loop e
-		in
-		try (loop e; false) with Exit -> true
-	in
+			let fn_is_override = function
+				| Some cf -> List.memq cf cl.cl_overrides
+				| None -> false
+			in
+			let is_override = fn_is_override get || fn_is_override set in
+			let visibility = if is_interface then "" else "public" in
+			let visibility, modifiers = get_fun_modifiers prop.cf_meta visibility [] in
+			let v_n = if is_static then "static" else if is_override && not is_interface then "override" else if is_virtual then "virtual" else "" in
+			gen_nocompletion w prop.cf_meta;
+
+			gen_field_decl w visibility v_n modifiers (t_s (run_follow gen t)) (change_field prop.cf_name);
+
+			let check cf = match cf with
+				| Some ({ cf_overloads = o :: _ } as cf) ->
+						gen.gcon.error "Property functions with more than one overload is currently unsupported" cf.cf_pos;
+						gen.gcon.error "Property functions with more than one overload is currently unsupported" o.cf_pos
+				| _ -> ()
+			in
+			check get;
+			check set;
 
-	let rec gen_class_field w ?(is_overload=false) is_static cl is_final cf =
-		gen_attributes w cf.cf_meta;
-		let is_interface = cl.cl_interface in
-		let name, is_new, is_explicit_iface = match cf.cf_name with
-			| "new" -> snd cl.cl_path, true, false
-			| name when String.contains name '.' ->
-				let fn_name, path = parse_explicit_iface name in
-				(s_type_path path) ^ "." ^ fn_name, false, true
-			| name -> try
-				let binop = PMap.find name binops_names in
-				"operator " ^ s_binop binop, false, false
-			with | Not_found -> try
-				let unop = PMap.find name unops_names in
-				"operator " ^ s_unop unop, false, false
-			with | Not_found ->
-				if Meta.has (Meta.Custom "?prop_impl") cf.cf_meta || Meta.has (Meta.Custom ":cs_event_impl") cf.cf_meta then
-					"_" ^ name, false, false
-				else
-					name, false, false
+			write w " ";
+			if is_interface then begin
+				write w "{ ";
+				let s = ref "" in
+				(match prop.cf_kind with Var { v_read = AccCall } -> write w "get;"; s := " "; | _ -> ());
+				(match prop.cf_kind with Var { v_write = AccCall } -> print w "%sset;" !s | _ -> ());
+				write w " }";
+				newline w;
+			end else begin
+				begin_block w;
+				(match get with
+					| Some cf ->
+						print w "get { return _get_%s(); }" prop.cf_name;
+						newline w;
+						cf.cf_meta <- (Meta.Custom "?prop_impl", [], null_pos) :: cf.cf_meta;
+					| None -> ());
+				(match set with
+					| Some cf ->
+						print w "set { _set_%s(value); }" prop.cf_name;
+						newline w;
+						cf.cf_meta <- (Meta.Custom "?prop_impl", [], null_pos) :: cf.cf_meta;
+					| None -> ());
+				end_block w;
+				newline w;
+				newline w;
+			end;
 		in
-		let rec loop_static cl =
-			match is_static, cl.cl_super with
-				| false, _ -> []
-				| true, None -> []
-				| true, Some(cl,_) ->
-					 (try
-							let cf2 = PMap.find cf.cf_name cl.cl_statics in
-							CastDetect.type_eq gen EqStrict cf.cf_type cf2.cf_type;
-							["new"]
-						with
-							| Not_found | Unify_error _ ->
-									loop_static cl
-						)
+
+		let needs_unchecked e =
+			let rec loop e = match e.eexpr with
+			(* a non-zero integer constant means that we want unchecked context *)
+			| TConst (TInt i) when i <> Int32.zero ->
+				raise Exit
+
+			(* don't recurse into explicit checked blocks *)
+			| TCall ({ eexpr = TLocal({ v_name = "__checked__" }) }, _) ->
+				()
+
+			(* skip reflection field hashes as they are safe *)
+			| TNew ({ cl_path = (["haxe"; "lang"],"DynamicObject") }, [], [_; e1; _; e2]) ->
+				loop e1;
+				loop e2
+			| TNew ({ cl_path = (["haxe"; "lang"],"Closure") }, [], [eo; _; _]) ->
+				loop eo
+			| TCall ({ eexpr = TField (_, FStatic ({ cl_path = ["haxe"; "lang"],"Runtime" },
+					{ cf_name = "getField" | "setField" | "getField_f" | "setField_f" | "callField" })) },
+					eo :: _ :: _ :: rest) ->
+				loop eo;
+				List.iter loop rest
+
+			| _ ->
+				Type.iter loop e
+			in
+			try (loop e; false) with Exit -> true
 		in
-		let modf = loop_static cl in
-
-		(match cf.cf_kind with
-			| Var _
-			| Method (MethDynamic) when not (Type.is_extern_field cf) ->
-				(if is_overload || List.exists (fun cf -> cf.cf_expr <> None) cf.cf_overloads then
-					gen.gcon.error "Only normal (non-dynamic) methods can be overloaded" cf.cf_pos);
-				if not is_interface then begin
-					let access, modifiers = get_fun_modifiers cf.cf_meta "public" [] in
+
+		let rec gen_class_field w ?(is_overload=false) is_static cl is_final cf =
+			gen_attributes w cf.cf_meta;
+			let is_interface = cl.cl_interface in
+			let name, is_new, is_explicit_iface = match cf.cf_name with
+				| "new" -> snd cl.cl_path, true, false
+				| name when String.contains name '.' ->
+					let fn_name, path = parse_explicit_iface name in
+					(s_type_path path) ^ "." ^ fn_name, false, true
+				| name -> try
+					let binop = PMap.find name binops_names in
+					"operator " ^ s_binop binop, false, false
+				with | Not_found -> try
+					let unop = PMap.find name unops_names in
+					"operator " ^ s_unop unop, false, false
+				with | Not_found ->
+					if Meta.has (Meta.Custom "?prop_impl") cf.cf_meta || Meta.has (Meta.Custom ":cs_event_impl") cf.cf_meta then
+						"_" ^ name, false, false
+					else
+						name, false, false
+			in
+			let rec loop_static cl =
+				match is_static, cl.cl_super with
+					| false, _ -> []
+					| true, None -> []
+					| true, Some(cl,_) ->
+						(try
+								let cf2 = PMap.find cf.cf_name cl.cl_statics in
+								CastDetect.type_eq gen EqStrict cf.cf_type cf2.cf_type;
+								["new"]
+							with
+								| Not_found | Unify_error _ ->
+										loop_static cl
+							)
+			in
+			let modf = loop_static cl in
+
+			(match cf.cf_kind with
+				| Var _
+				| Method (MethDynamic) when not (Type.is_extern_field cf) ->
+					(if is_overload || List.exists (fun cf -> cf.cf_expr <> None) cf.cf_overloads then
+						gen.gcon.error "Only normal (non-dynamic) methods can be overloaded" cf.cf_pos);
+					if not is_interface then begin
+						let access, modifiers = get_fun_modifiers cf.cf_meta "public" [] in
+						let modifiers = modifiers @ modf in
+						gen_nocompletion w cf.cf_meta;
+						gen_field_decl w access (if is_static then "static" else "") modifiers (t_s (run_follow gen cf.cf_type)) (change_field name);
+						(match cf.cf_expr with
+							| Some e ->
+								write w " = ";
+								expr_s w e;
+							| None -> ()
+						);
+						write w ";"
+					end (* TODO see how (get,set) variable handle when they are interfaces *)
+				| Method _ when Type.is_extern_field cf || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
+					List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then
+						gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf
+					) cf.cf_overloads
+				| Var _ | Method MethDynamic -> ()
+				| Method mkind ->
+					List.iter (fun cf ->
+						if cl.cl_interface || cf.cf_expr <> None then
+							gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf
+					) cf.cf_overloads;
+					let is_virtual = not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false in
+					let is_virtual = if not is_virtual || Meta.has Meta.Final cf.cf_meta then false else is_virtual in
+					let is_override = List.memq cf cl.cl_overrides in
+					let is_override = is_override || match cf.cf_name, follow cf.cf_type with
+						| "Equals", TFun([_,_,targ], tret) ->
+							(match follow targ, follow tret with
+								| TDynamic _, TAbstract({ a_path = ([], "Bool") }, []) -> true
+								| _ -> false)
+						| "GetHashCode", TFun([],_) -> true
+						| _ -> false
+					in
+					let is_override = if Meta.has (Meta.Custom "?prop_impl") cf.cf_meta then false else is_override in
+
+					let is_virtual = is_virtual && not (Meta.has Meta.Final cl.cl_meta) && not (is_interface) in
+					let visibility = if is_interface then "" else "public" in
+
+					let visibility, modifiers = get_fun_modifiers cf.cf_meta visibility [] in
 					let modifiers = modifiers @ modf in
+					let visibility, is_virtual = if is_explicit_iface then "",false else if visibility = "private" then "private",false else visibility, is_virtual in
+					let v_n = if is_static then "static" else if is_override && not is_interface then "override" else if is_virtual then "virtual" else "" in
+					let cf_type = if is_override && not is_overload && not (Meta.has Meta.Overload cf.cf_meta) then match field_access gen (TInst(cl, List.map snd cl.cl_params)) cf.cf_name with | FClassField(_,_,_,_,_,actual_t,_) -> actual_t | _ -> assert false else cf.cf_type in
+					let ret_type, args = match follow cf_type with | TFun (strbtl, t) -> (t, strbtl) | _ -> assert false in
 					gen_nocompletion w cf.cf_meta;
-					gen_field_decl w access (if is_static then "static" else "") modifiers (t_s (run_follow gen cf.cf_type)) (change_field name);
+
+					(* public static void funcName *)
+					gen_field_decl w visibility v_n modifiers (if not is_new then (rett_s (run_follow gen ret_type)) else "") (change_field name);
+
+					let params, params_ext = get_string_params cl cf.cf_params in
+					(* <T>(string arg1, object arg2) with T : object *)
 					(match cf.cf_expr with
-						| Some e ->
-							write w " = ";
-							expr_s w e;
-						| None -> ()
+					| Some { eexpr = TFunction tf } ->
+							print w "%s(%s)%s" (params) (String.concat ", " (List.map2 (fun (var, _) (_,_,t) -> sprintf "%s %s" (argt_s t) (change_id var.v_name)) tf.tf_args args)) (params_ext)
+					| _ ->
+							print w "%s(%s)%s" (params) (String.concat ", " (List.map (fun (name, _, t) -> sprintf "%s %s" (argt_s t) (change_id name)) args)) (params_ext)
 					);
-					write w ";"
-				end (* TODO see how (get,set) variable handle when they are interfaces *)
-			| Method _ when Type.is_extern_field cf || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
-				List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then
-					gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf
-				) cf.cf_overloads
-			| Var _ | Method MethDynamic -> ()
-			| Method mkind ->
-				List.iter (fun cf ->
-					if cl.cl_interface || cf.cf_expr <> None then
-						gen_class_field w ~is_overload:true is_static cl (Meta.has Meta.Final cf.cf_meta) cf
-				) cf.cf_overloads;
-				let is_virtual = not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false in
-				let is_virtual = if not is_virtual || Meta.has Meta.Final cf.cf_meta then false else is_virtual in
-				let is_override = List.memq cf cl.cl_overrides in
-				let is_override = is_override || match cf.cf_name, follow cf.cf_type with
-					| "Equals", TFun([_,_,targ], tret) ->
-						(match follow targ, follow tret with
-							| TDynamic _, TAbstract({ a_path = ([], "Bool") }, []) -> true
-							| _ -> false)
-					| "GetHashCode", TFun([],_) -> true
-					| _ -> false
-				in
-				let is_override = if Meta.has (Meta.Custom "?prop_impl") cf.cf_meta then false else is_override in
-
-				let is_virtual = is_virtual && not (Meta.has Meta.Final cl.cl_meta) && not (is_interface) in
-				let visibility = if is_interface then "" else "public" in
-
-				let visibility, modifiers = get_fun_modifiers cf.cf_meta visibility [] in
-				let modifiers = modifiers @ modf in
-				let visibility, is_virtual = if is_explicit_iface then "",false else if visibility = "private" then "private",false else visibility, is_virtual in
-				let v_n = if is_static then "static" else if is_override && not is_interface then "override" else if is_virtual then "virtual" else "" in
-				let cf_type = if is_override && not is_overload && not (Meta.has Meta.Overload cf.cf_meta) then match field_access gen (TInst(cl, List.map snd cl.cl_params)) cf.cf_name with | FClassField(_,_,_,_,_,actual_t,_) -> actual_t | _ -> assert false else cf.cf_type in
-				let ret_type, args = match follow cf_type with | TFun (strbtl, t) -> (t, strbtl) | _ -> assert false in
-				gen_nocompletion w cf.cf_meta;
-
-				(* public static void funcName *)
-				gen_field_decl w visibility v_n modifiers (if not is_new then (rett_s (run_follow gen ret_type)) else "") (change_field name);
-
-				let params, params_ext = get_string_params cl cf.cf_params in
-				(* <T>(string arg1, object arg2) with T : object *)
-				(match cf.cf_expr with
-				| Some { eexpr = TFunction tf } ->
-						print w "%s(%s)%s" (params) (String.concat ", " (List.map2 (fun (var, _) (_,_,t) -> sprintf "%s %s" (argt_s t) (change_id var.v_name)) tf.tf_args args)) (params_ext)
-				| _ ->
-						print w "%s(%s)%s" (params) (String.concat ", " (List.map (fun (name, _, t) -> sprintf "%s %s" (argt_s t) (change_id name)) args)) (params_ext)
-				);
-				if is_interface then
-					write w ";"
-				else begin
-					write w " ";
-					let rec loop meta =
-						match meta with
-							| [] ->
-								let expr = match cf.cf_expr with
-									| None -> mk (TBlock([])) t_dynamic null_pos
-									| Some s ->
-										match s.eexpr with
-											| TFunction tf ->
-												mk_block (tf.tf_expr)
-											| _ -> assert false (* FIXME *)
-								in
-
-								let write_method_expr e =
-									match e.eexpr with
-									| TBlock [] ->
-										begin_block w;
-										end_block w
-									| TBlock _ ->
-										let unchecked = needs_unchecked e in
-										if unchecked then (begin_block w; write w "unchecked ");
-										let t = Common.timer ["expression to string"] in
-										expr_s w e;
-										t();
-										line_reset_directive w;
-										if unchecked then end_block w
-									| _ ->
-										assert false
-								in
+					if is_interface then
+						write w ";"
+					else begin
+						write w " ";
+						let rec loop meta =
+							match meta with
+								| [] ->
+									let expr = match cf.cf_expr with
+										| None -> mk (TBlock([])) t_dynamic null_pos
+										| Some s ->
+											match s.eexpr with
+												| TFunction tf ->
+													mk_block (tf.tf_expr)
+												| _ -> assert false (* FIXME *)
+									in
 
-								(if is_new then begin
-									let rec get_super_call el =
-										match el with
-											| ( { eexpr = TCall( { eexpr = TConst(TSuper) }, _) } as call) :: rest ->
-												Some call, rest
-											| ( { eexpr = TBlock(bl) } as block ) :: rest ->
-												let ret, mapped = get_super_call bl in
-												ret, ( { block with eexpr = TBlock(mapped) } :: rest )
-											| _ ->
-												None, el
+									let write_method_expr e =
+										match e.eexpr with
+										| TBlock [] ->
+											begin_block w;
+											end_block w
+										| TBlock _ ->
+											let unchecked = needs_unchecked e in
+											if unchecked then (begin_block w; write w "unchecked ");
+											let t = Common.timer ["expression to string"] in
+											expr_s w e;
+											t();
+											line_reset_directive w;
+											if unchecked then end_block w
+										| _ ->
+											assert false
 									in
-									match expr.eexpr with
-										| TBlock(bl) ->
-											let super_call, rest = get_super_call bl in
-											(match super_call with
-												| None -> ()
-												| Some sc ->
-													write w ": ";
-													let t = Common.timer ["expression to string"] in
-													expr_s w sc;
-													write w " ";
-													t()
-											);
-											write_method_expr { expr with eexpr = TBlock(rest) }
-										| _ -> assert false
-								end else
-									write_method_expr expr
-								)
-							| (Meta.FunctionCode, [Ast.EConst (Ast.String contents),_],_) :: tl ->
-								begin_block w;
-								write w contents;
-								end_block w
-							| _ :: tl -> loop tl
-					in
-					loop cf.cf_meta
 
-				end);
-			newline w;
-			newline w;
-	in
+									(if is_new then begin
+										let rec get_super_call el =
+											match el with
+												| ( { eexpr = TCall( { eexpr = TConst(TSuper) }, _) } as call) :: rest ->
+													Some call, rest
+												| ( { eexpr = TBlock(bl) } as block ) :: rest ->
+													let ret, mapped = get_super_call bl in
+													ret, ( { block with eexpr = TBlock(mapped) } :: rest )
+												| _ ->
+													None, el
+										in
+										match expr.eexpr with
+											| TBlock(bl) ->
+												let super_call, rest = get_super_call bl in
+												(match super_call with
+													| None -> ()
+													| Some sc ->
+														write w ": ";
+														let t = Common.timer ["expression to string"] in
+														expr_s w sc;
+														write w " ";
+														t()
+												);
+												write_method_expr { expr with eexpr = TBlock(rest) }
+											| _ -> assert false
+									end else
+										write_method_expr expr
+									)
+								| (Meta.FunctionCode, [Ast.EConst (Ast.String contents),_],_) :: tl ->
+									begin_block w;
+									write w contents;
+									end_block w
+								| _ :: tl -> loop tl
+						in
+						loop cf.cf_meta
 
-	let check_special_behaviors w cl = match cl.cl_kind with
-	| KAbstractImpl _ -> ()
-	| _ ->
-		(* get/set pairs *)
-		let pairs = ref PMap.empty in
-		(try
-			let get = PMap.find "__get" cl.cl_fields in
-			List.iter (fun cf ->
-				let args,ret = get_fun cf.cf_type in
-				match args with
-				| [_,_,idx] -> pairs := PMap.add (t_s idx) ( t_s ret, Some cf, None ) !pairs
-				| _ -> gen.gcon.warning "The __get function must have exactly one argument (the index)" cf.cf_pos
-			) (get :: get.cf_overloads)
-		with | Not_found -> ());
-		(try
-			let set = PMap.find "__set" cl.cl_fields in
-			List.iter (fun cf ->
-				let args, ret = get_fun cf.cf_type in
-				match args with
-				| [_,_,idx; _,_,v] -> (try
-					let vt, g, _ = PMap.find (t_s idx) !pairs in
-					let tvt = t_s v in
-					if vt <> tvt then gen.gcon.warning "The __get function of same index has a different type from this __set function" cf.cf_pos;
-					pairs := PMap.add (t_s idx) (vt, g, Some cf) !pairs
-				with | Not_found ->
-					pairs := PMap.add (t_s idx) (t_s v, None, Some cf) !pairs)
-				| _ ->
-					gen.gcon.warning "The __set function must have exactly two arguments (index, value)" cf.cf_pos
-			) (set :: set.cf_overloads)
-		with | Not_found -> ());
-		PMap.iter (fun idx (v, get, set) ->
-			print w "public %s this[%s index]" v idx;
-				begin_block w;
-				(match get with
-				| None -> ()
-				| Some _ ->
-					write w "get";
-					begin_block w;
-					write w "return this.__get(index);";
-					end_block w);
-				(match set with
-				| None -> ()
-				| Some _ ->
-					write w "set";
+					end);
+				newline w;
+				newline w;
+		in
+
+		let check_special_behaviors w cl = match cl.cl_kind with
+		| KAbstractImpl _ -> ()
+		| _ ->
+			(* get/set pairs *)
+			let pairs = ref PMap.empty in
+			(try
+				let get = PMap.find "__get" cl.cl_fields in
+				List.iter (fun cf ->
+					let args,ret = get_fun cf.cf_type in
+					match args with
+					| [_,_,idx] -> pairs := PMap.add (t_s idx) ( t_s ret, Some cf, None ) !pairs
+					| _ -> gen.gcon.warning "The __get function must have exactly one argument (the index)" cf.cf_pos
+				) (get :: get.cf_overloads)
+			with | Not_found -> ());
+			(try
+				let set = PMap.find "__set" cl.cl_fields in
+				List.iter (fun cf ->
+					let args, ret = get_fun cf.cf_type in
+					match args with
+					| [_,_,idx; _,_,v] -> (try
+						let vt, g, _ = PMap.find (t_s idx) !pairs in
+						let tvt = t_s v in
+						if vt <> tvt then gen.gcon.warning "The __get function of same index has a different type from this __set function" cf.cf_pos;
+						pairs := PMap.add (t_s idx) (vt, g, Some cf) !pairs
+					with | Not_found ->
+						pairs := PMap.add (t_s idx) (t_s v, None, Some cf) !pairs)
+					| _ ->
+						gen.gcon.warning "The __set function must have exactly two arguments (index, value)" cf.cf_pos
+				) (set :: set.cf_overloads)
+			with | Not_found -> ());
+			PMap.iter (fun idx (v, get, set) ->
+				print w "public %s this[%s index]" v idx;
 					begin_block w;
-					write w "this.__set(index,value);";
-					end_block w);
-				end_block w) !pairs;
-		(if not (PMap.is_empty !pairs) then try
-			let get = PMap.find "__get" cl.cl_fields in
-			let idx_t, v_t = match follow get.cf_type with
-				| TFun([_,_,arg_t],ret_t) ->
-					t_s (run_follow gen arg_t), t_s (run_follow gen ret_t)
-				| _ -> gen.gcon.error "The __get function must be a function with one argument. " get.cf_pos; assert false
-			in
-			List.iter (fun (cl,args) ->
-				match cl.cl_array_access with
+					(match get with
 					| None -> ()
-					| Some t ->
-						let changed_t = apply_params cl.cl_params (List.map (fun _ -> t_dynamic) cl.cl_params) t in
-						let t_as_s = t_s (run_follow gen changed_t) in
-						print w "%s %s.this[int key]" t_as_s (t_s (TInst(cl, args)));
-							begin_block w;
+					| Some _ ->
+						write w "get";
+						begin_block w;
+						write w "return this.__get(index);";
+						end_block w);
+					(match set with
+					| None -> ()
+					| Some _ ->
+						write w "set";
+						begin_block w;
+						write w "this.__set(index,value);";
+						end_block w);
+					end_block w) !pairs;
+			(if not (PMap.is_empty !pairs) then try
+				let get = PMap.find "__get" cl.cl_fields in
+				let idx_t, v_t = match follow get.cf_type with
+					| TFun([_,_,arg_t],ret_t) ->
+						t_s (run_follow gen arg_t), t_s (run_follow gen ret_t)
+					| _ -> gen.gcon.error "The __get function must be a function with one argument. " get.cf_pos; assert false
+				in
+				List.iter (fun (cl,args) ->
+					match cl.cl_array_access with
+						| None -> ()
+						| Some t ->
+							let changed_t = apply_params cl.cl_params (List.map (fun _ -> t_dynamic) cl.cl_params) t in
+							let t_as_s = t_s (run_follow gen changed_t) in
+							print w "%s %s.this[int key]" t_as_s (t_s (TInst(cl, args)));
+								begin_block w;
+								write w "get";
+								begin_block w;
+									print w "return ((%s) this.__get(key));" t_as_s;
+								end_block w;
+								write w "set";
+								begin_block w;
+									print w "this.__set(key, (%s) value);" v_t;
+								end_block w;
+							end_block w;
+							newline w;
+							newline w
+				) cl.cl_implements
+			with | Not_found -> ());
+			if cl.cl_interface && is_hxgen (TClassDecl cl) && is_some cl.cl_array_access then begin
+				let changed_t = apply_params cl.cl_params (List.map (fun _ -> t_dynamic) cl.cl_params) (get cl.cl_array_access) in
+				print w "%s this[int key]" (t_s (run_follow gen changed_t));
+				begin_block w;
+					write w "get;";
+					newline w;
+					write w "set;";
+					newline w;
+				end_block w;
+				newline w;
+				newline w
+			end;
+			(try
+				if cl.cl_interface then raise Not_found;
+				let cf = PMap.find "toString" cl.cl_fields in
+				(if List.exists (fun c -> c.cf_name = "toString") cl.cl_overrides then raise Not_found);
+				(match cf.cf_type with
+					| TFun([], ret) ->
+						(match real_type ret with
+							| TInst( { cl_path = ([], "String") }, []) ->
+								write w "public override string ToString()";
+								begin_block w;
+								write w "return this.toString();";
+								end_block w;
+								newline w;
+								newline w
+							| _ ->
+								gen.gcon.error "A toString() function should return a String!" cf.cf_pos
+						)
+					| _ -> ()
+				)
+			with | Not_found -> ());
+			(try
+				if cl.cl_interface then raise Not_found;
+				let cf = PMap.find "finalize" cl.cl_fields in
+				(if List.exists (fun c -> c.cf_name = "finalize") cl.cl_overrides then raise Not_found);
+				(match cf.cf_type with
+					| TFun([], ret) ->
+						(match real_type ret with
+							| TAbstract( { a_path = ([], "Void") }, []) ->
+								write w "~";
+								write w (snd cl.cl_path);
+								write w "()";
+								begin_block w;
+								write w "this.finalize();";
+								end_block w;
+								newline w;
+								newline w
+							| _ ->
+								gen.gcon.error "A finalize() function should be Void->Void!" cf.cf_pos
+						)
+					| _ -> ()
+				)
+			with | Not_found -> ());
+			(* properties *)
+			let handle_prop static f =
+				match f.cf_kind with
+				| Method _ -> ()
+				| Var v when not (Type.is_extern_field f) -> ()
+				| Var v ->
+					let prop acc = match acc with
+						| AccNo | AccNever | AccCall -> true
+						| _ -> false
+					in
+					if prop v.v_read && prop v.v_write && (v.v_read = AccCall || v.v_write = AccCall) then begin
+						let this = if static then
+							ExprBuilder.make_static_this cl f.cf_pos
+						else
+							{ eexpr = TConst TThis; etype = TInst(cl,List.map snd cl.cl_params); epos = f.cf_pos }
+						in
+						print w "public %s%s %s" (if static then "static " else "") (t_s f.cf_type) (Dotnet.netname_to_hx f.cf_name);
+						begin_block w;
+						(match v.v_read with
+						| AccCall ->
 							write w "get";
 							begin_block w;
-								print w "return ((%s) this.__get(key));" t_as_s;
-							end_block w;
+							write w "return ";
+							expr_s w this;
+							print w ".get_%s();" f.cf_name;
+							end_block w
+						| _ -> ());
+						(match v.v_write with
+						| AccCall ->
 							write w "set";
 							begin_block w;
-								print w "this.__set(key, (%s) value);" v_t;
-							end_block w;
+							expr_s w this;
+							print w ".set_%s(value);" f.cf_name;
+							end_block w
+						| _ -> ());
 						end_block w;
-						newline w;
-						newline w
-			) cl.cl_implements
-		with | Not_found -> ());
-		if cl.cl_interface && is_hxgen (TClassDecl cl) && is_some cl.cl_array_access then begin
-			let changed_t = apply_params cl.cl_params (List.map (fun _ -> t_dynamic) cl.cl_params) (get cl.cl_array_access) in
-			print w "%s this[int key]" (t_s (run_follow gen changed_t));
-			begin_block w;
-				write w "get;";
-				newline w;
-				write w "set;";
-				newline w;
-			end_block w;
+					end
+			in
+			if Meta.has Meta.BridgeProperties cl.cl_meta then begin
+				List.iter (handle_prop true) cl.cl_ordered_statics;
+				List.iter (handle_prop false) cl.cl_ordered_fields;
+			end
+		in
+
+		let gen_class w cl =
+			write w "#pragma warning disable 109, 114, 219, 429, 168, 162";
 			newline w;
-			newline w
-		end;
-		(try
-			if cl.cl_interface then raise Not_found;
-			let cf = PMap.find "toString" cl.cl_fields in
-			(if List.exists (fun c -> c.cf_name = "toString") cl.cl_overrides then raise Not_found);
-			(match cf.cf_type with
-				| TFun([], ret) ->
-					(match real_type ret with
-						| TInst( { cl_path = ([], "String") }, []) ->
-							write w "public override string ToString()";
-							begin_block w;
-							write w "return this.toString();";
-							end_block w;
-							newline w;
-							newline w
-						| _ ->
-							gen.gcon.error "A toString() function should return a String!" cf.cf_pos
-					)
-				| _ -> ()
-			)
-		with | Not_found -> ());
-		(try
-			if cl.cl_interface then raise Not_found;
-			let cf = PMap.find "finalize" cl.cl_fields in
-			(if List.exists (fun c -> c.cf_name = "finalize") cl.cl_overrides then raise Not_found);
-			(match cf.cf_type with
-				| TFun([], ret) ->
-					(match real_type ret with
-						| TAbstract( { a_path = ([], "Void") }, []) ->
-							write w "~";
-							write w (snd cl.cl_path);
-							write w "()";
-							begin_block w;
-							write w "this.finalize();";
-							end_block w;
-							newline w;
-							newline w
-						| _ ->
-							gen.gcon.error "A finalize() function should be Void->Void!" cf.cf_pos
-					)
-				| _ -> ()
-			)
-		with | Not_found -> ());
-		(* properties *)
-		let handle_prop static f =
-			match f.cf_kind with
-			| Method _ -> ()
-			| Var v when not (Type.is_extern_field f) -> ()
-			| Var v ->
-				let prop acc = match acc with
-					| AccNo | AccNever | AccCall -> true
-					| _ -> false
-				in
-				if prop v.v_read && prop v.v_write && (v.v_read = AccCall || v.v_write = AccCall) then begin
-					let this = if static then
-						ExprBuilder.make_static_this cl f.cf_pos
-					else
-						{ eexpr = TConst TThis; etype = TInst(cl,List.map snd cl.cl_params); epos = f.cf_pos }
-					in
-					print w "public %s%s %s" (if static then "static " else "") (t_s f.cf_type) (Dotnet.netname_to_hx f.cf_name);
+			let should_close = match change_ns (TClassDecl cl) (fst (cl.cl_path)) with
+				| [] -> false
+				| ns ->
+					print w "namespace %s " (String.concat "." ns);
 					begin_block w;
-					(match v.v_read with
-					| AccCall ->
-						write w "get";
+					true
+			in
+
+			(try
+				let _,m,_ = Meta.get (Meta.Custom "generic_iface") cl.cl_meta in
+				let rec loop i acc =
+					if i == 0 then
+						acc
+					else
+						"object" :: (loop (pred i) acc)
+				in
+				let tparams = loop (match m with [(EConst(Int s),_)] -> int_of_string s | _ -> assert false) [] in
+				cl.cl_meta <- (Meta.Meta, [
+					EConst(String("global::haxe.lang.GenericInterface(typeof(global::" ^ module_s (TClassDecl cl) ^ "<" ^ String.concat ", " tparams ^ ">))") ), cl.cl_pos
+				], cl.cl_pos) :: cl.cl_meta
+			with Not_found ->
+				());
+
+			gen_attributes w cl.cl_meta;
+
+			let is_main =
+				match gen.gcon.main_class with
+					| Some ( (_,"Main") as path) when path = cl.cl_path && not cl.cl_interface ->
+						(*
+							for cases where the main class is called Main, there will be a problem with creating the entry point there.
+							In this special case, a special entry point class will be created
+						*)
+						write w "public class EntryPoint__Main ";
 						begin_block w;
-						write w "return ";
-						expr_s w this;
-						print w ".get_%s();" f.cf_name;
-						end_block w
-					| _ -> ());
-					(match v.v_write with
-					| AccCall ->
-						write w "set";
+						write w "public static void Main() ";
 						begin_block w;
-						expr_s w this;
-						print w ".set_%s(value);" f.cf_name;
-						end_block w
-					| _ -> ());
-					end_block w;
-				end
-		in
-		if Meta.has Meta.BridgeProperties cl.cl_meta then begin
-			List.iter (handle_prop true) cl.cl_ordered_statics;
-			List.iter (handle_prop false) cl.cl_ordered_fields;
-		end
-	in
-
-	let gen_class w cl =
-		write w "#pragma warning disable 109, 114, 219, 429, 168, 162";
-		newline w;
-		let should_close = match change_ns (TClassDecl cl) (fst (cl.cl_path)) with
-			| [] -> false
-			| ns ->
-				print w "namespace %s " (String.concat "." ns);
-				begin_block w;
-				true
-		in
+						(if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w);
+						(match gen.gcon.main with
+							| None ->
+								expr_s w { eexpr = TTypeExpr(TClassDecl cl); etype = t_dynamic; epos = null_pos };
+								write w ".main();"
+							| Some expr ->
+								expr_s w (mk_block expr));
+						end_block w;
+						end_block w;
+						newline w;
+						false
+					| Some path when path = cl.cl_path && not cl.cl_interface -> true
+					| _ -> false
+			in
 
-		(try
-			let _,m,_ = Meta.get (Meta.Custom "generic_iface") cl.cl_meta in
-			let rec loop i acc =
-				if i == 0 then
-					acc
-				else
-					"object" :: (loop (pred i) acc)
+			let clt, access, modifiers = get_class_modifiers cl.cl_meta (if cl.cl_interface then "interface" else "class") "public" [] in
+			let is_final = clt = "struct" || Meta.has Meta.Final cl.cl_meta in
+
+			let modifiers = [access] @ modifiers in
+			print w "%s %s %s" (String.concat " " modifiers) clt (change_clname (snd cl.cl_path));
+			(* type parameters *)
+			let params, params_ext = get_string_params cl cl.cl_params in
+			let extends_implements = (match cl.cl_super with | None -> [] | Some (cl,p) -> [path_param_s (TClassDecl cl) cl.cl_path p]) @ (List.map (fun (cl,p) -> path_param_s (TClassDecl cl) cl.cl_path p) cl.cl_implements) in
+			(match extends_implements with
+				| [] -> print w "%s%s " params params_ext
+				| _ -> print w "%s : %s%s " params (String.concat ", " extends_implements) params_ext);
+			(* class head ok: *)
+			(* public class Test<A> : X, Y, Z where A : Y *)
+			begin_block w;
+			newline w;
+			(* our constructor is expected to be a normal "new" function *
+			if !strict_mode && is_some cl.cl_constructor then assert false;*)
+
+			let rec loop meta =
+				match meta with
+					| [] -> ()
+					| (Meta.ClassCode, [Ast.EConst (Ast.String contents),_],_) :: tl ->
+						write w contents
+					| _ :: tl -> loop tl
 			in
-			let tparams = loop (match m with [(EConst(Int s),_)] -> int_of_string s | _ -> assert false) [] in
-			cl.cl_meta <- (Meta.Meta, [
-				EConst(String("global::haxe.lang.GenericInterface(typeof(global::" ^ module_s (TClassDecl cl) ^ "<" ^ String.concat ", " tparams ^ ">))") ), cl.cl_pos
-			], cl.cl_pos) :: cl.cl_meta
-		with Not_found ->
-			());
-
-		gen_attributes w cl.cl_meta;
-
-		let is_main =
-			match gen.gcon.main_class with
-				| Some ( (_,"Main") as path) when path = cl.cl_path && not cl.cl_interface ->
-					(*
-						for cases where the main class is called Main, there will be a problem with creating the entry point there.
-						In this special case, a special entry point class will be created
-					*)
-					write w "public class EntryPoint__Main ";
-					begin_block w;
-					write w "public static void Main() ";
-					begin_block w;
-					(if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w);
-					(match gen.gcon.main with
-						| None ->
-							expr_s w { eexpr = TTypeExpr(TClassDecl cl); etype = t_dynamic; epos = null_pos };
-							write w ".main();"
-						| Some expr ->
+			loop cl.cl_meta;
+
+			if is_main then begin
+				write w "public static void Main()";
+				begin_block w;
+				(if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w);
+				(match gen.gcon.main with
+					| None ->
+						write w "main();";
+					| Some expr ->
 							expr_s w (mk_block expr));
-					end_block w;
-					end_block w;
+				end_block w
+			end;
+
+			(match cl.cl_init with
+				| None -> ()
+				| Some init ->
+					print w "static %s() " (snd cl.cl_path);
+					if needs_unchecked init then begin
+						begin_block w;
+						write w "unchecked ";
+						expr_s w (mk_block init);
+						end_block w;
+					end else
+						expr_s w (mk_block init);
+					line_reset_directive w;
 					newline w;
-					false
-				| Some path when path = cl.cl_path && not cl.cl_interface -> true
-				| _ -> false
-		in
+					newline w
+			);
 
-		let clt, access, modifiers = get_class_modifiers cl.cl_meta (if cl.cl_interface then "interface" else "class") "public" [] in
-		let is_final = clt = "struct" || Meta.has Meta.Final cl.cl_meta in
-
-		let modifiers = [access] @ modifiers in
-		print w "%s %s %s" (String.concat " " modifiers) clt (change_clname (snd cl.cl_path));
-		(* type parameters *)
-		let params, params_ext = get_string_params cl cl.cl_params in
-		let extends_implements = (match cl.cl_super with | None -> [] | Some (cl,p) -> [path_param_s (TClassDecl cl) cl.cl_path p]) @ (List.map (fun (cl,p) -> path_param_s (TClassDecl cl) cl.cl_path p) cl.cl_implements) in
-		(match extends_implements with
-			| [] -> print w "%s%s " params params_ext
-			| _ -> print w "%s : %s%s " params (String.concat ", " extends_implements) params_ext);
-		(* class head ok: *)
-		(* public class Test<A> : X, Y, Z where A : Y *)
-		begin_block w;
-		newline w;
-		(* our constructor is expected to be a normal "new" function *
-		if !strict_mode && is_some cl.cl_constructor then assert false;*)
-
-		let rec loop meta =
-			match meta with
-				| [] -> ()
-				| (Meta.ClassCode, [Ast.EConst (Ast.String contents),_],_) :: tl ->
-					write w contents
-				| _ :: tl -> loop tl
-		in
-		loop cl.cl_meta;
+			(* collect properties and events *)
+			let partition cf cflist =
+				let events, props, nonprops = ref [], ref [], ref [] in
 
-		if is_main then begin
-			write w "public static void Main()";
-			begin_block w;
-			(if Hashtbl.mem gen.gtypes (["cs"], "Boot") then write w "global::cs.Boot.init();"; newline w);
-			(match gen.gcon.main with
-				| None ->
-					write w "main();";
-				| Some expr ->
-						expr_s w (mk_block expr));
-			end_block w
-		end;
+				List.iter (fun v -> match v.cf_kind with
+					| Var { v_read = AccCall } | Var { v_write = AccCall } when Type.is_extern_field v && Meta.has Meta.Property v.cf_meta ->
+						props := (v.cf_name, ref (v, v.cf_type, None, None)) :: !props;
+					| Var { v_read = AccNormal; v_write = AccNormal } when Meta.has Meta.Event v.cf_meta ->
+						events := (v.cf_name, ref (v, v.cf_type, false, None, None)) :: !events;
+					| _ ->
+						nonprops := v :: !nonprops;
+				) cflist;
+
+				let events, nonprops = !events, !nonprops in
+
+				let t = TInst(cl, List.map snd cl.cl_params) in
+				let find_prop name = try
+						List.assoc name !props
+					with | Not_found -> match field_access gen t name with
+						| FClassField (_,_,decl,v,_,t,_) when is_extern_prop (TInst(cl,List.map snd cl.cl_params)) name ->
+							let ret = ref (v,t,None,None) in
+							props := (name, ret) :: !props;
+							ret
+						| _ -> raise Not_found
+				in
 
-		(match cl.cl_init with
-			| None -> ()
-			| Some init ->
-				print w "static %s() " (snd cl.cl_path);
-				if needs_unchecked init then begin
-					begin_block w;
-					write w "unchecked ";
-					expr_s w (mk_block init);
-					end_block w;
-				end else
-					expr_s w (mk_block init);
-				line_reset_directive w;
-				newline w;
-				newline w
-		);
+				let find_event name = List.assoc name events in
 
-		(* collect properties and events *)
-		let partition cf cflist =
-			let events, props, nonprops = ref [], ref [], ref [] in
+				let is_empty_function cf = match cf.cf_expr with
+					| Some {eexpr = TFunction { tf_expr = {eexpr = TBlock []}}} -> true
+					| _ -> false
+				in
 
-			List.iter (fun v -> match v.cf_kind with
-				| Var { v_read = AccCall } | Var { v_write = AccCall } when Type.is_extern_field v && Meta.has Meta.Property v.cf_meta ->
-					props := (v.cf_name, ref (v, v.cf_type, None, None)) :: !props;
-				| Var { v_read = AccNormal; v_write = AccNormal } when Meta.has Meta.Event v.cf_meta ->
-					events := (v.cf_name, ref (v, v.cf_type, false, None, None)) :: !events;
-				| _ ->
-					nonprops := v :: !nonprops;
-			) cflist;
-
-			let events, nonprops = !events, !nonprops in
-
-			let t = TInst(cl, List.map snd cl.cl_params) in
-			let find_prop name = try
-					List.assoc name !props
-				with | Not_found -> match field_access gen t name with
-					| FClassField (_,_,decl,v,_,t,_) when is_extern_prop (TInst(cl,List.map snd cl.cl_params)) name ->
-						let ret = ref (v,t,None,None) in
-						props := (name, ret) :: !props;
-						ret
-					| _ -> raise Not_found
+				let interf = cl.cl_interface in
+				(* get all functions that are getters/setters *)
+				let nonprops = List.filter (function
+					| cf when String.starts_with cf.cf_name "get_" -> (try
+						(* find the property *)
+						let prop = find_prop (String.sub cf.cf_name 4 (String.length cf.cf_name - 4)) in
+						let v, t, get, set = !prop in
+						assert (get = None);
+						prop := (v,t,Some cf,set);
+						not interf
+					with | Not_found -> true)
+					| cf when String.starts_with cf.cf_name "set_" -> (try
+						(* find the property *)
+						let prop = find_prop (String.sub cf.cf_name 4 (String.length cf.cf_name - 4)) in
+						let v, t, get, set = !prop in
+						assert (set = None);
+						prop := (v,t,get,Some cf);
+						not interf
+					with | Not_found -> true)
+					| cf when String.starts_with cf.cf_name "add_" -> (try
+						let event = find_event (String.sub cf.cf_name 4 (String.length cf.cf_name - 4)) in
+						let v, t, _, add, remove = !event in
+						assert (add = None);
+						let custom = not (is_empty_function cf) in
+						event := (v, t, custom, Some cf, remove);
+						false
+					with | Not_found -> true)
+					| cf when String.starts_with cf.cf_name "remove_" -> (try
+						let event = find_event (String.sub cf.cf_name 7 (String.length cf.cf_name - 7)) in
+						let v, t, _, add, remove = !event in
+						assert (remove = None);
+						let custom = not (is_empty_function cf) in
+						event := (v, t, custom, add, Some cf);
+						false
+					with | Not_found -> true)
+					| _ -> true
+				) nonprops in
+
+				let nonprops = ref nonprops in
+				List.iter (fun (n,r) ->
+					let ev, t, custom, add, remove = !r in
+					match add, remove with
+					| Some add, Some remove ->
+						if custom && not cl.cl_interface then
+							nonprops := add :: remove :: !nonprops
+					| _ -> assert false (* shouldn't happen because Filters.check_cs_events makes sure methods are present *)
+				) events;
+
+				let evts = List.map (fun(_,v) -> !v) events in
+				let ret = List.map (fun (_,v) -> !v) !props in
+				let ret = List.filter (function | (_,_,None,None) -> false | _ -> true) ret in
+				evts, ret, List.rev !nonprops
 			in
 
-			let find_event name = List.assoc name events in
+			let fevents, fprops, fnonprops = partition cl cl.cl_ordered_fields in
+			let sevents, sprops, snonprops = partition cl cl.cl_ordered_statics in
+			(if is_some cl.cl_constructor then gen_class_field w false cl is_final (get cl.cl_constructor));
+			if not cl.cl_interface then begin
+				(* we don't want to generate properties for abstract implementation classes, because they don't have object to work with *)
+				List.iter (gen_event w true cl) sevents;
+				if (match cl.cl_kind with KAbstractImpl _ -> false | _ -> true) then List.iter (gen_prop w true cl is_final) sprops;
+				List.iter (gen_class_field w true cl is_final) snonprops
+			end;
+			List.iter (gen_event w false cl) fevents;
+			List.iter (gen_prop w false cl is_final) fprops;
+			List.iter (gen_class_field w false cl is_final) fnonprops;
+			check_special_behaviors w cl;
+			end_block w;
+			if cl.cl_interface && cl.cl_ordered_statics <> [] then begin
+				print w "public class %s__Statics_" (snd cl.cl_path);
+				begin_block w;
+				List.iter (gen_class_field w true { cl with cl_interface = false } is_final) cl.cl_ordered_statics;
+				end_block w
+			end;
+			if should_close then end_block w
+		in
 
-			let is_empty_function cf = match cf.cf_expr with
-				| Some {eexpr = TFunction { tf_expr = {eexpr = TBlock []}}} -> true
-				| _ -> false
-			in
 
-			let interf = cl.cl_interface in
-			(* get all functions that are getters/setters *)
-			let nonprops = List.filter (function
-				| cf when String.starts_with cf.cf_name "get_" -> (try
-					(* find the property *)
-					let prop = find_prop (String.sub cf.cf_name 4 (String.length cf.cf_name - 4)) in
-					let v, t, get, set = !prop in
-					assert (get = None);
-					prop := (v,t,Some cf,set);
-					not interf
-				with | Not_found -> true)
-				| cf when String.starts_with cf.cf_name "set_" -> (try
-					(* find the property *)
-					let prop = find_prop (String.sub cf.cf_name 4 (String.length cf.cf_name - 4)) in
-					let v, t, get, set = !prop in
-					assert (set = None);
-					prop := (v,t,get,Some cf);
-					not interf
-				with | Not_found -> true)
-				| cf when String.starts_with cf.cf_name "add_" -> (try
-					let event = find_event (String.sub cf.cf_name 4 (String.length cf.cf_name - 4)) in
-					let v, t, _, add, remove = !event in
-					assert (add = None);
-					let custom = not (is_empty_function cf) in
-					event := (v, t, custom, Some cf, remove);
-					false
-				with | Not_found -> true)
-				| cf when String.starts_with cf.cf_name "remove_" -> (try
-					let event = find_event (String.sub cf.cf_name 7 (String.length cf.cf_name - 7)) in
-					let v, t, _, add, remove = !event in
-					assert (remove = None);
-					let custom = not (is_empty_function cf) in
-					event := (v, t, custom, add, Some cf);
-					false
-				with | Not_found -> true)
-				| _ -> true
-			) nonprops in
-
-			let nonprops = ref nonprops in
-			List.iter (fun (n,r) ->
-				let ev, t, custom, add, remove = !r in
-				match add, remove with
-				| Some add, Some remove ->
-					if custom && not cl.cl_interface then
-						nonprops := add :: remove :: !nonprops
-				| _ -> assert false (* shouldn't happen because Filters.check_cs_events makes sure methods are present *)
-			) events;
-
-			let evts = List.map (fun(_,v) -> !v) events in
-			let ret = List.map (fun (_,v) -> !v) !props in
-			let ret = List.filter (function | (_,_,None,None) -> false | _ -> true) ret in
-			evts, ret, List.rev !nonprops
-		in
+		let gen_enum w e =
+			let should_close = match change_ns (TEnumDecl e) (fst e.e_path) with
+				| [] -> false
+				| ns ->
+					print w "namespace %s" (String.concat "." ns);
+					begin_block w;
+					true
+			in
+			gen_attributes w e.e_meta;
 
-		let fevents, fprops, fnonprops = partition cl cl.cl_ordered_fields in
-		let sevents, sprops, snonprops = partition cl cl.cl_ordered_statics in
-		(if is_some cl.cl_constructor then gen_class_field w false cl is_final (get cl.cl_constructor));
-		if not cl.cl_interface then begin
-			(* we don't want to generate properties for abstract implementation classes, because they don't have object to work with *)
-			List.iter (gen_event w true cl) sevents;
-			if (match cl.cl_kind with KAbstractImpl _ -> false | _ -> true) then List.iter (gen_prop w true cl is_final) sprops;
-			List.iter (gen_class_field w true cl is_final) snonprops
-		end;
-		List.iter (gen_event w false cl) fevents;
-		List.iter (gen_prop w false cl is_final) fprops;
-		List.iter (gen_class_field w false cl is_final) fnonprops;
-		check_special_behaviors w cl;
-		end_block w;
-		if cl.cl_interface && cl.cl_ordered_statics <> [] then begin
-			print w "public class %s__Statics_" (snd cl.cl_path);
+			print w "public enum %s" (change_clname (snd e.e_path));
 			begin_block w;
-			List.iter (gen_class_field w true { cl with cl_interface = false } is_final) cl.cl_ordered_statics;
-			end_block w
-		end;
-		if should_close then end_block w
-	in
+			write w (String.concat ", " (List.map (change_id) e.e_names));
+			end_block w;
 
+			if should_close then end_block w
+		in
 
-	let gen_enum w e =
-		let should_close = match change_ns (TEnumDecl e) (fst e.e_path) with
-			| [] -> false
-			| ns ->
-				print w "namespace %s" (String.concat "." ns);
-				begin_block w;
-				true
+		let module_type_gen w md_tp =
+			let file_start = len w = 0 in
+			let requires_root = no_root && file_start in
+			if file_start then
+				Codegen.map_source_header gen.gcon (fun s -> print w "// %s\n" s);
+			reset_temps();
+			match md_tp with
+				| TClassDecl cl ->
+					if not cl.cl_extern then begin
+						(if requires_root then write w "using haxe.root;\n"; newline w;);
+						gen_class w cl;
+						newline w;
+						newline w
+					end;
+					(not cl.cl_extern)
+				| TEnumDecl e ->
+					if not e.e_extern && not (Meta.has Meta.Class e.e_meta) then begin
+						(if requires_root then write w "using haxe.root;\n"; newline w;);
+						gen_enum w e;
+						newline w;
+						newline w
+					end;
+					(not e.e_extern)
+				| TAbstractDecl _
+				| TTypeDecl _ ->
+					false
 		in
-		gen_attributes w e.e_meta;
 
-		print w "public enum %s" (change_clname (snd e.e_path));
-		begin_block w;
-		write w (String.concat ", " (List.map (change_id) e.e_names));
-		end_block w;
+		(* generate source code *)
+		init_ctx gen;
+
+		Hashtbl.add gen.gspecial_vars "__rethrow__" true;
+		Hashtbl.add gen.gspecial_vars "__typeof__" true;
+		Hashtbl.add gen.gspecial_vars "__label__" true;
+		Hashtbl.add gen.gspecial_vars "__goto__" true;
+		Hashtbl.add gen.gspecial_vars "__is__" true;
+		Hashtbl.add gen.gspecial_vars "__as__" true;
+		Hashtbl.add gen.gspecial_vars "__cs__" true;
+
+		Hashtbl.add gen.gspecial_vars "__checked__" true;
+		Hashtbl.add gen.gspecial_vars "__lock__" true;
+		Hashtbl.add gen.gspecial_vars "__fixed__" true;
+		Hashtbl.add gen.gspecial_vars "__unsafe__" true;
+		Hashtbl.add gen.gspecial_vars "__addressOf__" true;
+		Hashtbl.add gen.gspecial_vars "__valueOf__" true;
+		Hashtbl.add gen.gspecial_vars "__sizeof__" true;
+		Hashtbl.add gen.gspecial_vars "__stackalloc__" true;
+
+		Hashtbl.add gen.gspecial_vars "__delegate__" true;
+		Hashtbl.add gen.gspecial_vars "__array__" true;
+		Hashtbl.add gen.gspecial_vars "__ptr__" true;
+
+		Hashtbl.add gen.gsupported_conversions (["haxe"; "lang"], "Null") (fun t1 t2 -> true);
+		let last_needs_box = gen.gneeds_box in
+		gen.gneeds_box <- (fun t -> match (gen.greal_type t) with
+			| TAbstract( ( { a_path = ["cs"], "Pointer" }, _ ) )
+			| TInst( { cl_path = ["cs"], "Pointer" }, _ )
+			| TInst( { cl_path = (["haxe"; "lang"], "Null") }, _ ) -> true
+			| _ -> last_needs_box t);
+
+		gen.greal_type <- real_type;
+		gen.greal_type_param <- change_param_type;
+
+		SetHXGen.run_filter gen.gcon gen.gtypes_list;
+
+		(* before running the filters, follow all possible types *)
+		(* this is needed so our module transformations don't break some core features *)
+		(* like multitype selection *)
+		let run_follow_gen = run_follow gen in
+		let rec type_map e = Type.map_expr_type (fun e->type_map e) (run_follow_gen)	(fun tvar-> tvar.v_type <- (run_follow_gen tvar.v_type); tvar) e in
+		let super_map (cl,tl) = (cl, List.map run_follow_gen tl) in
+		List.iter (function
+			| TClassDecl cl ->
+					let all_fields = (Option.map_default (fun cf -> [cf]) [] cl.cl_constructor) @ cl.cl_ordered_fields @ cl.cl_ordered_statics in
+					List.iter (fun cf ->
+						cf.cf_type <- run_follow_gen cf.cf_type;
+						cf.cf_expr <- Option.map type_map cf.cf_expr;
+
+						(* add @:skipReflection to @:event vars *)
+						match cf.cf_kind with
+						| Var _ when (Meta.has Meta.Event cf.cf_meta) && not (Meta.has Meta.SkipReflection cf.cf_meta) ->
+							cf.cf_meta <- (Meta.SkipReflection, [], null_pos) :: cf.cf_meta;
+						| _ -> ()
+
+					) all_fields;
+				cl.cl_dynamic <- Option.map run_follow_gen cl.cl_dynamic;
+				cl.cl_array_access <- Option.map run_follow_gen cl.cl_array_access;
+				cl.cl_init <- Option.map type_map cl.cl_init;
+				cl.cl_super <- Option.map super_map cl.cl_super;
+				cl.cl_implements <- List.map super_map cl.cl_implements
+			| _ -> ()
+			) gen.gtypes_list;
+
+		let tp_v = alloc_var "$type_param" t_dynamic in
+		let mk_tp t pos = { eexpr = TLocal(tp_v); etype = t; epos = pos } in
+		gen.gparam_func_call <- (fun ecall efield params elist ->
+			match efield.eexpr with
+			| TField(_, FEnum _) ->
+				{ ecall with eexpr = TCall(efield, elist) }
+			| _ ->
+				{ ecall with eexpr = TCall(efield, (List.map (fun t -> mk_tp t ecall.epos) params) @ elist) }
+		);
 
-		if should_close then end_block w
-	in
+		if not erase_generics then HardNullableSynf.configure gen
+			(fun e ->
+				match e.eexpr, real_type e.etype with
+					| TConst TThis, _ when gen.gcurrent_path = (["haxe";"lang"], "Null") ->
+						e
+					| _, TInst({ cl_path = (["haxe";"lang"], "Null") }, [t]) ->
+						let e = { e with eexpr = TParenthesis(e) } in
+						{ (mk_field_access gen e "value" e.epos) with etype = t }
+					| _ ->
+						trace (debug_type e.etype); gen.gcon.error "This expression is not a Nullable expression" e.epos; assert false
+			)
+			(fun v t has_value ->
+				match has_value, real_type v.etype with
+					| true, TDynamic _ | true, TAnon _ | true, TMono _ ->
+						{
+							eexpr = TCall(mk_static_field_access_infer null_t "ofDynamic" v.epos [t], [mk_tp t v.epos; v]);
+							etype = TInst(null_t, [t]);
+							epos = v.epos
+						}
+					| _ ->
+						{ eexpr = TNew(null_t, [t], [gen.ghandle_cast t v.etype v; { eexpr = TConst(TBool has_value); etype = gen.gcon.basic.tbool; epos = v.epos } ]); etype = TInst(null_t, [t]); epos = v.epos }
+			)
+			(fun e ->
+				{
+					eexpr = TCall(
+						{ (mk_field_access gen { (mk_paren e) with etype = real_type e.etype } "toDynamic" e.epos) with etype = TFun([], t_dynamic) },
+						[]);
+					etype = t_dynamic;
+					epos = e.epos
+				}
+			)
+			(fun e ->
+				mk_field_access gen { e with etype = real_type e.etype } "hasValue" e.epos
+			)
+			(fun e1 e2 ->
+				mk (TCall(mk_field_access gen e1 "Equals" e1.epos, [e2])) basic.tbool e1.epos
+			);
 
-	let module_type_gen w md_tp =
-		let file_start = len w = 0 in
-		let requires_root = no_root && file_start in
-		if file_start then
-			Codegen.map_source_header gen.gcon (fun s -> print w "// %s\n" s);
-		reset_temps();
-		match md_tp with
-			| TClassDecl cl ->
-				if not cl.cl_extern then begin
-					(if requires_root then write w "using haxe.root;\n"; newline w;);
-					gen_class w cl;
-					newline w;
-					newline w
-				end;
-				(not cl.cl_extern)
-			| TEnumDecl e ->
-				if not e.e_extern && not (Meta.has Meta.Class e.e_meta) then begin
-					(if requires_root then write w "using haxe.root;\n"; newline w;);
-					gen_enum w e;
-					newline w;
-					newline w
-				end;
-				(not e.e_extern)
-			| TAbstractDecl _
-			| TTypeDecl _ ->
-				false
-	in
 
-	(* generate source code *)
-	init_ctx gen;
-
-	Hashtbl.add gen.gspecial_vars "__rethrow__" true;
-	Hashtbl.add gen.gspecial_vars "__typeof__" true;
-	Hashtbl.add gen.gspecial_vars "__label__" true;
-	Hashtbl.add gen.gspecial_vars "__goto__" true;
-	Hashtbl.add gen.gspecial_vars "__is__" true;
-	Hashtbl.add gen.gspecial_vars "__as__" true;
-	Hashtbl.add gen.gspecial_vars "__cs__" true;
-
-	Hashtbl.add gen.gspecial_vars "__checked__" true;
-	Hashtbl.add gen.gspecial_vars "__lock__" true;
-	Hashtbl.add gen.gspecial_vars "__fixed__" true;
-	Hashtbl.add gen.gspecial_vars "__unsafe__" true;
-	Hashtbl.add gen.gspecial_vars "__addressOf__" true;
-	Hashtbl.add gen.gspecial_vars "__valueOf__" true;
-	Hashtbl.add gen.gspecial_vars "__sizeof__" true;
-	Hashtbl.add gen.gspecial_vars "__stackalloc__" true;
-
-	Hashtbl.add gen.gspecial_vars "__delegate__" true;
-	Hashtbl.add gen.gspecial_vars "__array__" true;
-	Hashtbl.add gen.gspecial_vars "__ptr__" true;
-
-	Hashtbl.add gen.gsupported_conversions (["haxe"; "lang"], "Null") (fun t1 t2 -> true);
-	let last_needs_box = gen.gneeds_box in
-	gen.gneeds_box <- (fun t -> match (gen.greal_type t) with
-		| TAbstract( ( { a_path = ["cs"], "Pointer" }, _ ) )
-		| TInst( { cl_path = ["cs"], "Pointer" }, _ )
-		| TInst( { cl_path = (["haxe"; "lang"], "Null") }, _ ) -> true
-		| _ -> last_needs_box t);
-
-	gen.greal_type <- real_type;
-	gen.greal_type_param <- change_param_type;
-
-	SetHXGen.run_filter gen.gcon gen.gtypes_list;
-
-	(* before running the filters, follow all possible types *)
-	(* this is needed so our module transformations don't break some core features *)
-	(* like multitype selection *)
-	let run_follow_gen = run_follow gen in
-	let rec type_map e = Type.map_expr_type (fun e->type_map e) (run_follow_gen)	(fun tvar-> tvar.v_type <- (run_follow_gen tvar.v_type); tvar) e in
-	let super_map (cl,tl) = (cl, List.map run_follow_gen tl) in
-	List.iter (function
-		| TClassDecl cl ->
-				let all_fields = (Option.map_default (fun cf -> [cf]) [] cl.cl_constructor) @ cl.cl_ordered_fields @ cl.cl_ordered_statics in
-				List.iter (fun cf ->
-					cf.cf_type <- run_follow_gen cf.cf_type;
-					cf.cf_expr <- Option.map type_map cf.cf_expr;
+		let explicit_fn_name c tl fname =
+			path_param_s (TClassDecl c) c.cl_path tl ^ "." ^ fname
+		in
 
-					(* add @:skipReflection to @:event vars *)
-					match cf.cf_kind with
-					| Var _ when (Meta.has Meta.Event cf.cf_meta) && not (Meta.has Meta.SkipReflection cf.cf_meta) ->
-						cf.cf_meta <- (Meta.SkipReflection, [], null_pos) :: cf.cf_meta;
-					| _ -> ()
+		FixOverrides.configure ~explicit_fn_name:explicit_fn_name ~get_vmtype:real_type gen;
+		Normalize.configure gen ~metas:(Hashtbl.create 0);
 
-				) all_fields;
-			 cl.cl_dynamic <- Option.map run_follow_gen cl.cl_dynamic;
-			 cl.cl_array_access <- Option.map run_follow_gen cl.cl_array_access;
-			 cl.cl_init <- Option.map type_map cl.cl_init;
-			 cl.cl_super <- Option.map super_map cl.cl_super;
-			 cl.cl_implements <- List.map super_map cl.cl_implements
-		| _ -> ()
-		) gen.gtypes_list;
-
-	let tp_v = alloc_var "$type_param" t_dynamic in
-	let mk_tp t pos = { eexpr = TLocal(tp_v); etype = t; epos = pos } in
-	gen.gparam_func_call <- (fun ecall efield params elist ->
-		match efield.eexpr with
-		| TField(_, FEnum _) ->
-			{ ecall with eexpr = TCall(efield, elist) }
-		| _ ->
-			{ ecall with eexpr = TCall(efield, (List.map (fun t -> mk_tp t ecall.epos) params) @ elist) }
-	);
-
-	if not erase_generics then HardNullableSynf.configure gen
-		(fun e ->
-			match e.eexpr, real_type e.etype with
-				| TConst TThis, _ when gen.gcurrent_path = (["haxe";"lang"], "Null") ->
-					e
-				| _, TInst({ cl_path = (["haxe";"lang"], "Null") }, [t]) ->
-					let e = { e with eexpr = TParenthesis(e) } in
-					{ (mk_field_access gen e "value" e.epos) with etype = t }
-				| _ ->
-					trace (debug_type e.etype); gen.gcon.error "This expression is not a Nullable expression" e.epos; assert false
-		)
-		(fun v t has_value ->
-			match has_value, real_type v.etype with
-				| true, TDynamic _ | true, TAnon _ | true, TMono _ ->
-					{
-						eexpr = TCall(mk_static_field_access_infer null_t "ofDynamic" v.epos [t], [mk_tp t v.epos; v]);
-						etype = TInst(null_t, [t]);
-						epos = v.epos
-					}
-				| _ ->
-					{ eexpr = TNew(null_t, [t], [gen.ghandle_cast t v.etype v; { eexpr = TConst(TBool has_value); etype = gen.gcon.basic.tbool; epos = v.epos } ]); etype = TInst(null_t, [t]); epos = v.epos }
-		)
-		(fun e ->
-			{
-				eexpr = TCall(
-					{ (mk_field_access gen { (mk_paren e) with etype = real_type e.etype } "toDynamic" e.epos) with etype = TFun([], t_dynamic) },
-					[]);
-				etype = t_dynamic;
-				epos = e.epos
-			}
-		)
-		(fun e ->
-			mk_field_access gen { e with etype = real_type e.etype } "hasValue" e.epos
-		)
-		(fun e1 e2 ->
-			mk (TCall(mk_field_access gen e1 "Equals" e1.epos, [e2])) basic.tbool e1.epos
-		);
+		AbstractImplementationFix.configure gen;
 
+		let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 in
+		ClosuresToClass.configure gen closure_t;
 
-	let explicit_fn_name c tl fname =
-		path_param_s (TClassDecl c) c.cl_path tl ^ "." ^ fname
-	in
+		let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in
+		EnumToClass2.configure gen enum_base;
 
-	FixOverrides.configure ~explicit_fn_name:explicit_fn_name ~get_vmtype:real_type gen;
-	Normalize.configure gen ~metas:(Hashtbl.create 0);
+		InterfaceVarsDeleteModf.configure gen;
+		InterfaceProps.configure gen;
 
-	AbstractImplementationFix.configure gen;
+		let dynamic_object = (get_cl (get_type gen (["haxe";"lang"],"DynamicObject")) ) in
 
-	let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 in
-	ClosuresToClass.configure gen closure_t;
+		let object_iface = get_cl (get_type gen (["haxe";"lang"],"IHxObject")) in
 
-	let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in
-	EnumToClass2.configure gen enum_base;
+		let empty_en = match get_type gen (["haxe";"lang"], "EmptyObject") with TEnumDecl e -> e | _ -> assert false in
+		let empty_ctor_type = TEnum(empty_en, []) in
+		let empty_en_expr = mk (TTypeExpr (TEnumDecl empty_en)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics empty_en) }) null_pos in
+		let empty_ctor_expr = mk (TField (empty_en_expr, FEnum(empty_en, PMap.find "EMPTY" empty_en.e_constrs))) empty_ctor_type null_pos in
+		OverloadingConstructor.configure ~empty_ctor_type:empty_ctor_type ~empty_ctor_expr:empty_ctor_expr gen;
 
-	InterfaceVarsDeleteModf.configure gen;
-	InterfaceProps.configure gen;
+		let rcf_static_find = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "findHash" null_pos [] in
+		let rcf_static_lookup = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "lookupHash" null_pos [] in
 
-	let dynamic_object = (get_cl (get_type gen (["haxe";"lang"],"DynamicObject")) ) in
+		let rcf_static_insert, rcf_static_remove =
+			if erase_generics then begin
+				let get_specialized_postfix t = match t with
+					| TAbstract({a_path = [],("Float" | "Int" as name)}, _) -> name
+					| TAnon _ | TDynamic _ -> "Dynamic"
+					| _ -> print_endline (debug_type t); assert false
+				in
+				(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) null_pos []),
+				(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) null_pos [])
+			end else
+				(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "insert" null_pos [t]),
+				(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "remove" null_pos [t])
+		in
 
-	let object_iface = get_cl (get_type gen (["haxe";"lang"],"IHxObject")) in
+		let can_be_float = like_float in
 
-	let empty_en = match get_type gen (["haxe";"lang"], "EmptyObject") with TEnumDecl e -> e | _ -> assert false in
-	let empty_ctor_type = TEnum(empty_en, []) in
-	let empty_en_expr = mk (TTypeExpr (TEnumDecl empty_en)) (TAnon { a_fields = PMap.empty; a_status = ref (EnumStatics empty_en) }) null_pos in
-	let empty_ctor_expr = mk (TField (empty_en_expr, FEnum(empty_en, PMap.find "EMPTY" empty_en.e_constrs))) empty_ctor_type null_pos in
-	OverloadingConstructor.configure ~empty_ctor_type:empty_ctor_type ~empty_ctor_expr:empty_ctor_expr gen;
+		let rcf_on_getset_field main_expr field_expr field may_hash may_set is_unsafe =
+			let is_float = can_be_float (real_type main_expr.etype) in
+			let fn_name = if is_some may_set then "setField" else "getField" in
+			let fn_name = if is_float then fn_name ^ "_f" else fn_name in
+			let pos = field_expr.epos in
 
-	let rcf_static_find = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "findHash" null_pos [] in
-	let rcf_static_lookup = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "lookupHash" null_pos [] in
+			let is_unsafe = { eexpr = TConst(TBool is_unsafe); etype = basic.tbool; epos = pos } in
 
-	let rcf_static_insert, rcf_static_remove =
-		if erase_generics then begin
-			let get_specialized_postfix t = match t with
-				| TAbstract({a_path = [],("Float" | "Int" as name)}, _) -> name
-				| TAnon _ | TDynamic _ -> "Dynamic"
-				| _ -> print_endline (debug_type t); assert false
+			let should_cast = match main_expr.etype with | TAbstract({ a_path = ([], "Float") }, []) -> false | _ -> true in
+			let infer = mk_static_field_access_infer runtime_cl fn_name field_expr.epos [] in
+			let first_args =
+				[ field_expr; { eexpr = TConst(TString field); etype = basic.tstring; epos = pos } ]
+				@ if is_some may_hash then [ { eexpr = TConst(TInt (get may_hash)); etype = basic.tint; epos = pos } ] else []
+			in
+			let args = first_args @ match is_float, may_set with
+				| true, Some(set) ->
+					[ if should_cast then mk_cast basic.tfloat set else set ]
+				| false, Some(set) ->
+					[ set ]
+				| _ ->
+					[ is_unsafe ]
 			in
-			(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) null_pos []),
-			(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) null_pos [])
-		end else
-			(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "insert" null_pos [t]),
-			(fun t -> mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) "remove" null_pos [t])
-	in
-
-	let can_be_float = like_float in
 
-	let rcf_on_getset_field main_expr field_expr field may_hash may_set is_unsafe =
-		let is_float = can_be_float (real_type main_expr.etype) in
-		let fn_name = if is_some may_set then "setField" else "getField" in
-		let fn_name = if is_float then fn_name ^ "_f" else fn_name in
-		let pos = field_expr.epos in
+			let call = { main_expr with eexpr = TCall(infer,args) } in
+			let call = if is_float && should_cast then mk_cast main_expr.etype call else call in
+			call
+		in
 
-		let is_unsafe = { eexpr = TConst(TBool is_unsafe); etype = basic.tbool; epos = pos } in
+		let rcf_on_call_field ecall field_expr field may_hash args =
+			let infer = mk_static_field_access_infer runtime_cl "callField" field_expr.epos [] in
 
-		let should_cast = match main_expr.etype with | TAbstract({ a_path = ([], "Float") }, []) -> false | _ -> true in
-		let infer = mk_static_field_access_infer runtime_cl fn_name field_expr.epos [] in
-		let first_args =
-			[ field_expr; { eexpr = TConst(TString field); etype = basic.tstring; epos = pos } ]
-			@ if is_some may_hash then [ { eexpr = TConst(TInt (get may_hash)); etype = basic.tint; epos = pos } ] else []
-		in
-		let args = first_args @ match is_float, may_set with
-			| true, Some(set) ->
-				[ if should_cast then mk_cast basic.tfloat set else set ]
-			| false, Some(set) ->
-				[ set ]
-			| _ ->
-				[ is_unsafe ]
-		in
+			let hash_arg = match may_hash with
+				| None -> []
+				| Some h -> [ { eexpr = TConst(TInt h); etype = basic.tint; epos = field_expr.epos } ]
+			in
 
-		let call = { main_expr with eexpr = TCall(infer,args) } in
-		let call = if is_float && should_cast then mk_cast main_expr.etype call else call in
-		call
-	in
+			let arr_call = if args <> [] then
+				{ eexpr = TArrayDecl args; etype = basic.tarray t_dynamic; epos = ecall.epos }
+			else
+				null (basic.tarray t_dynamic) ecall.epos
+			in
 
-	let rcf_on_call_field ecall field_expr field may_hash args =
-		let infer = mk_static_field_access_infer runtime_cl "callField" field_expr.epos [] in
+			let call_args =
+				[field_expr; { field_expr with eexpr = TConst(TString field); etype = basic.tstring } ]
+					@ hash_arg
+					@ [ arr_call ]
+			in
 
-		let hash_arg = match may_hash with
-			| None -> []
-			| Some h -> [ { eexpr = TConst(TInt h); etype = basic.tint; epos = field_expr.epos } ]
+			mk_cast ecall.etype { ecall with eexpr = TCall(infer, call_args) }
 		in
 
-		let arr_call = if args <> [] then
-			{ eexpr = TArrayDecl args; etype = basic.tarray t_dynamic; epos = ecall.epos }
+		add_cast_handler gen;
+		if not erase_generics then
+			TypeParams.RealTypeParams.configure gen (fun e t -> gen.gcon.warning ("Cannot cast to " ^ (debug_type t)) e.epos; mk_cast t e) ifaces (get_cl (get_type gen (["haxe";"lang"], "IGenericObject")))
 		else
-			null (basic.tarray t_dynamic) ecall.epos
-		in
+			TypeParams.RealTypeParams.RealTypeParamsModf.configure gen (TypeParams.RealTypeParams.RealTypeParamsModf.set_only_hxgeneric gen);
 
-		let call_args =
-			[field_expr; { field_expr with eexpr = TConst(TString field); etype = basic.tstring } ]
-				@ hash_arg
-				@ [ arr_call ]
+		let flookup_cl = get_cl (get_type gen (["haxe";"lang"], "FieldLookup")) in
+
+		let rcf_ctx =
+			ReflectionCFs.new_ctx
+				gen
+				closure_t
+				object_iface
+				true
+				rcf_on_getset_field
+				rcf_on_call_field
+				(fun hash hash_array length -> { hash with eexpr = TCall(rcf_static_find, [hash; hash_array; length]); etype=basic.tint })
+				(fun hash -> { hash with eexpr = TCall(rcf_static_lookup, [hash]); etype = gen.gcon.basic.tstring })
+				(fun hash_array length pos value ->
+					let ecall = mk (TCall(rcf_static_insert value.etype, [hash_array; length; pos; value])) (if erase_generics then hash_array.etype else basic.tvoid) hash_array.epos in
+					if erase_generics then { ecall with eexpr = TBinop(OpAssign, hash_array, ecall) } else ecall
+				)
+				(fun hash_array length pos ->
+					let t = gen.gclasses.nativearray_type hash_array.etype in
+					{ hash_array with eexpr = TCall(rcf_static_remove t, [hash_array; length; pos]); etype = gen.gcon.basic.tvoid }
+				)
+				(
+					let delete = mk_static_field_access_infer flookup_cl "deleteHashConflict" null_pos [] in
+					let get = mk_static_field_access_infer flookup_cl "getHashConflict" null_pos [] in
+					let set = mk_static_field_access_infer flookup_cl "setHashConflict" null_pos [] in
+					let add = mk_static_field_access_infer flookup_cl "addHashConflictNames" null_pos [] in
+					let conflict_t = TInst (get_cl (get_type gen (["haxe"; "lang"], "FieldHashConflict")), []) in
+					Some {
+						t = conflict_t;
+						get_conflict = (fun ehead ehash ename -> mk (TCall (get, [ehead; ehash; ename])) conflict_t ehead.epos);
+						set = (fun ehead ehash ename evalue -> mk (TCall (set, [ehead; ehash; ename; evalue])) basic.tvoid ehead.epos);
+						delete = (fun ehead ehash ename -> mk (TCall (delete, [ehead; ehash; ename])) basic.tbool ehead.epos);
+						add_names = (fun ehead earr -> mk (TCall (add, [ehead; earr])) basic.tvoid ehead.epos);
+					}
+				)
 		in
 
-		mk_cast ecall.etype { ecall with eexpr = TCall(infer, call_args) }
-	in
+		ReflectionCFs.UniversalBaseClass.configure gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object;
 
-	add_cast_handler gen;
-	if not erase_generics then
-		TypeParams.RealTypeParams.configure gen (fun e t -> gen.gcon.warning ("Cannot cast to " ^ (debug_type t)) e.epos; mk_cast t e) ifaces (get_cl (get_type gen (["haxe";"lang"], "IGenericObject")))
-	else
-		TypeParams.RealTypeParams.RealTypeParamsModf.configure gen (TypeParams.RealTypeParams.RealTypeParamsModf.set_only_hxgeneric gen);
+		ReflectionCFs.configure_dynamic_field_access rcf_ctx;
 
-	let flookup_cl = get_cl (get_type gen (["haxe";"lang"], "FieldLookup")) in
+		let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in
+		let varargs_cl = get_cl (get_type gen (["haxe";"lang"],"VarArgsFunction")) in
+		let dynamic_name = mk_internal_name "hx" "invokeDynamic" in
 
-	let rcf_ctx =
-		ReflectionCFs.new_ctx
-			gen
-			closure_t
-			object_iface
-			true
-			rcf_on_getset_field
-			rcf_on_call_field
-			(fun hash hash_array length -> { hash with eexpr = TCall(rcf_static_find, [hash; hash_array; length]); etype=basic.tint })
-			(fun hash -> { hash with eexpr = TCall(rcf_static_lookup, [hash]); etype = gen.gcon.basic.tstring })
-			(fun hash_array length pos value ->
-				let ecall = mk (TCall(rcf_static_insert value.etype, [hash_array; length; pos; value])) (if erase_generics then hash_array.etype else basic.tvoid) hash_array.epos in
-				if erase_generics then { ecall with eexpr = TBinop(OpAssign, hash_array, ecall) } else ecall
-			)
-			(fun hash_array length pos ->
-				let t = gen.gclasses.nativearray_type hash_array.etype in
-				{ hash_array with eexpr = TCall(rcf_static_remove t, [hash_array; length; pos]); etype = gen.gcon.basic.tvoid }
-			)
-			(
-				let delete = mk_static_field_access_infer flookup_cl "deleteHashConflict" null_pos [] in
-				let get = mk_static_field_access_infer flookup_cl "getHashConflict" null_pos [] in
-				let set = mk_static_field_access_infer flookup_cl "setHashConflict" null_pos [] in
-				let add = mk_static_field_access_infer flookup_cl "addHashConflictNames" null_pos [] in
-				let conflict_t = TInst (get_cl (get_type gen (["haxe"; "lang"], "FieldHashConflict")), []) in
-				Some {
-					t = conflict_t;
-					get_conflict = (fun ehead ehash ename -> mk (TCall (get, [ehead; ehash; ename])) conflict_t ehead.epos);
-					set = (fun ehead ehash ename evalue -> mk (TCall (set, [ehead; ehash; ename; evalue])) basic.tvoid ehead.epos);
-					delete = (fun ehead ehash ename -> mk (TCall (delete, [ehead; ehash; ename])) basic.tbool ehead.epos);
-					add_names = (fun ehead earr -> mk (TCall (add, [ehead; earr])) basic.tvoid ehead.epos);
-				}
-			)
-	in
+		List.iter (fun cl ->
+			List.iter (fun cf ->
+				if cf.cf_name = dynamic_name then cl.cl_overrides <- cf :: cl.cl_overrides
+			) cl.cl_ordered_fields
+		) [closure_cl; varargs_cl];
 
-	ReflectionCFs.UniversalBaseClass.configure gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object;
-
-	ReflectionCFs.configure_dynamic_field_access rcf_ctx;
-
-	let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in
-	let varargs_cl = get_cl (get_type gen (["haxe";"lang"],"VarArgsFunction")) in
-	let dynamic_name = mk_internal_name "hx" "invokeDynamic" in
-
-	List.iter (fun cl ->
-		List.iter (fun cf ->
-			if cf.cf_name = dynamic_name then cl.cl_overrides <- cf :: cl.cl_overrides
-		) cl.cl_ordered_fields
-	) [closure_cl; varargs_cl];
-
-	ReflectionCFs.implement_varargs_cl rcf_ctx ( get_cl (get_type gen (["haxe";"lang"], "VarArgsBase")) );
-
-	let slow_invoke = mk_static_field_access_infer (runtime_cl) "slowCallField" null_pos [] in
-	ReflectionCFs.configure rcf_ctx ~slow_invoke:(fun ethis efield eargs -> {
-		eexpr = TCall(slow_invoke, [ethis; efield; eargs]);
-		etype = t_dynamic;
-		epos = ethis.epos;
-	} ) object_iface;
-
-	ObjectDeclMap.configure gen (ReflectionCFs.implement_dynamic_object_ctor rcf_ctx dynamic_object);
-
-	InitFunction.configure gen;
-	TArrayTransform.configure gen (
-	fun e binop ->
-		match e.eexpr with
-			| TArray(e1, e2) ->
-				(match follow e1.etype with
-					| TDynamic _ | TAnon _ | TMono _ -> true
-					| TInst({ cl_kind = KTypeParameter _ }, _) -> true
-					| TInst(c,p) when erase_generics && is_hxgeneric (TClassDecl c) && is_hxgen (TClassDecl c) -> (match c.cl_path with
-						| [],"String"
-						| ["cs"],"NativeArray" -> false
-						| _ ->
-							true)
-					| _ -> match binop, change_param_type (t_to_md e1.etype) [e.etype] with
-						| Some(Ast.OpAssignOp _), ([TDynamic _] | [TAnon _]) ->
-							true
-						| _ -> false)
-			| _ -> assert false
-	) "__get" "__set";
+		ReflectionCFs.implement_varargs_cl rcf_ctx ( get_cl (get_type gen (["haxe";"lang"], "VarArgsBase")) );
 
-	let field_is_dynamic t field =
-		match field_access_esp gen (gen.greal_type t) field with
-			| FEnumField _ -> false
-			| FClassField (cl,p,_,_,_,t,_) ->
-				if not erase_generics then
-					false
-				else
-					let p = change_param_type (TClassDecl cl) p in
-					is_dynamic (apply_params cl.cl_params p t)
-			| _ -> true
-	in
+		let slow_invoke = mk_static_field_access_infer (runtime_cl) "slowCallField" null_pos [] in
+		ReflectionCFs.configure rcf_ctx ~slow_invoke:(fun ethis efield eargs -> {
+			eexpr = TCall(slow_invoke, [ethis; efield; eargs]);
+			etype = t_dynamic;
+			epos = ethis.epos;
+		} ) object_iface;
 
-	let is_dynamic_expr e = is_dynamic e.etype || match e.eexpr with
-		| TField(tf, f) -> field_is_dynamic tf.etype (f)
-		| _ -> false
-	in
+		ObjectDeclMap.configure gen (ReflectionCFs.implement_dynamic_object_ctor rcf_ctx dynamic_object);
 
-	let may_nullable t = match gen.gfollow#run_f t with
-		| TType({ t_path = ([], "Null") }, [t]) ->
-			(match follow t with
-				| TInst({ cl_path = ([], "String") }, [])
-				| TAbstract ({ a_path = ([], "Float") },[])
-				| TInst({ cl_path = (["haxe"], "Int32")}, [] )
-				| TInst({ cl_path = (["haxe"], "Int64")}, [] )
-				| TAbstract ({ a_path = ([], "Int") },[])
-				| TAbstract ({ a_path = ([], "Bool") },[]) -> Some t
-				| TAbstract _ when like_float t -> Some t
-				| t when is_cs_basic_type t -> Some t
-				| _ -> None )
-		| _ -> None
-	in
+		InitFunction.configure gen;
+		TArrayTransform.configure gen (
+		fun e binop ->
+			match e.eexpr with
+				| TArray(e1, e2) ->
+					(match follow e1.etype with
+						| TDynamic _ | TAnon _ | TMono _ -> true
+						| TInst({ cl_kind = KTypeParameter _ }, _) -> true
+						| TInst(c,p) when erase_generics && is_hxgeneric (TClassDecl c) && is_hxgen (TClassDecl c) -> (match c.cl_path with
+							| [],"String"
+							| ["cs"],"NativeArray" -> false
+							| _ ->
+								true)
+						| _ -> match binop, change_param_type (t_to_md e1.etype) [e.etype] with
+							| Some(Ast.OpAssignOp _), ([TDynamic _] | [TAnon _]) ->
+								true
+							| _ -> false)
+				| _ -> assert false
+		) "__get" "__set";
 
-	let is_double t = like_float t && not (like_int t) in
-	let is_int t = like_int t in
+		let field_is_dynamic t field =
+			match field_access_esp gen (gen.greal_type t) field with
+				| FEnumField _ -> false
+				| FClassField (cl,p,_,_,_,t,_) ->
+					if not erase_generics then
+						false
+					else
+						let p = change_param_type (TClassDecl cl) p in
+						is_dynamic (apply_params cl.cl_params p t)
+				| _ -> true
+		in
 
-	let is_null t = match real_type t with
-		| TInst( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> true
-		| _ -> false
-	in
+		let is_dynamic_expr e = is_dynamic e.etype || match e.eexpr with
+			| TField(tf, f) -> field_is_dynamic tf.etype (f)
+			| _ -> false
+		in
 
-	let is_null_expr e = is_null e.etype || match e.eexpr with
-		| TField(tf, f) -> (match field_access_esp gen (real_type tf.etype) (f) with
-			| FClassField(_,_,_,_,_,actual_t,_) -> is_null actual_t
-			| _ -> false)
-		| _ -> false
-	in
+		let may_nullable t = match gen.gfollow#run_f t with
+			| TType({ t_path = ([], "Null") }, [t]) ->
+				(match follow t with
+					| TInst({ cl_path = ([], "String") }, [])
+					| TAbstract ({ a_path = ([], "Float") },[])
+					| TInst({ cl_path = (["haxe"], "Int32")}, [] )
+					| TInst({ cl_path = (["haxe"], "Int64")}, [] )
+					| TAbstract ({ a_path = ([], "Int") },[])
+					| TAbstract ({ a_path = ([], "Bool") },[]) -> Some t
+					| TAbstract _ when like_float t -> Some t
+					| t when is_cs_basic_type t -> Some t
+					| _ -> None )
+			| _ -> None
+		in
+
+		let is_double t = like_float t && not (like_int t) in
+		let is_int t = like_int t in
 
-	let should_handle_opeq t =
-		match real_type t with
-			| TDynamic _ | TAnon _ | TMono _
-			| TInst( { cl_kind = KTypeParameter _ }, _ )
+		let is_null t = match real_type t with
 			| TInst( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> true
 			| _ -> false
-	in
+		in
 
-	let string_cl = match gen.gcon.basic.tstring with
-		| TInst(c,[]) -> c
-		| _ -> assert false
-	in
+		let is_null_expr e = is_null e.etype || match e.eexpr with
+			| TField(tf, f) -> (match field_access_esp gen (real_type tf.etype) (f) with
+				| FClassField(_,_,_,_,_,actual_t,_) -> is_null actual_t
+				| _ -> false)
+			| _ -> false
+		in
 
-	let is_undefined e = match e.eexpr with
-		| TLocal { v_name = "__undefined__" } | TField(_,FStatic({cl_path=["haxe";"lang"],"Runtime"},{cf_name="undefined"})) -> true
-		| _ -> false
-	in
+		let should_handle_opeq t =
+			match real_type t with
+				| TDynamic _ | TAnon _ | TMono _
+				| TInst( { cl_kind = KTypeParameter _ }, _ )
+				| TInst( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> true
+				| _ -> false
+		in
 
-	DynamicOperators.configure gen
-		(fun e -> match e.eexpr with
-			| TBinop (Ast.OpEq, e1, e2)
-			| TBinop (Ast.OpNotEq, e1, e2) ->
-				(
-					(* dont touch (v == null) and (null == v) comparisons because they are handled by HardNullableSynf later *)
-					match e1.eexpr, e2.eexpr with
-					| TConst(TNull), _ when (not (is_tparam e2.etype) && is_dynamic e2.etype) || is_null_expr e2 ->
-						false
-					| _, TConst(TNull) when (not (is_tparam e1.etype) && is_dynamic e1.etype) || is_null_expr e1 ->
-						false
-					| _ when is_undefined e1 || is_undefined e2 ->
-						false
-					| _ ->
-						should_handle_opeq e1.etype || should_handle_opeq e2.etype
-				)
-			| TBinop (Ast.OpAssignOp Ast.OpAdd, e1, e2) ->
-				is_dynamic_expr e1 || is_null_expr e1 || is_string e.etype
-			| TBinop (Ast.OpAdd, e1, e2) -> is_dynamic e1.etype || is_dynamic e2.etype || is_tparam e1.etype || is_tparam e2.etype || is_string e1.etype || is_string e2.etype || is_string e.etype
-			| TBinop (Ast.OpLt, e1, e2)
-			| TBinop (Ast.OpLte, e1, e2)
-			| TBinop (Ast.OpGte, e1, e2)
-			| TBinop (Ast.OpGt, e1, e2) -> is_dynamic e.etype || is_dynamic_expr e1 || is_dynamic_expr e2 || is_string e1.etype || is_string e2.etype
-			| TBinop (_, e1, e2) -> is_dynamic e.etype || is_dynamic_expr e1 || is_dynamic_expr e2
-			| TUnop (_, _, e1) -> is_dynamic_expr e1 || is_null_expr e1 (* we will see if the expression is Null<T> also, as the unwrap from Unop will be the same *)
-			| _ -> false)
-		(fun e1 e2 ->
-			let is_basic = is_cs_basic_type (follow e1.etype) || is_cs_basic_type (follow e2.etype) in
-			let is_ref = if is_basic then false else match follow e1.etype, follow e2.etype with
-				| TDynamic _, _
-				| _, TDynamic _
-				| TInst( { cl_path = ([], "String") }, [] ), _
-				| _, TInst( { cl_path = ([], "String") }, [] )
-				| TInst( { cl_kind = KTypeParameter _ }, [] ), _
-				| _, TInst( { cl_kind = KTypeParameter _ }, [] ) -> false
-				| _, _ -> true
-			in
+		let string_cl = match gen.gcon.basic.tstring with
+			| TInst(c,[]) -> c
+			| _ -> assert false
+		in
 
-			let static = mk_static_field_access_infer (runtime_cl) (if is_ref then "refEq" else "eq") e1.epos [] in
-			{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tbool; epos=e1.epos }
-		)
-		(fun e e1 e2 ->
-			match may_nullable e1.etype, may_nullable e2.etype with
-				| Some t1, Some t2 ->
-					let t1, t2 = if is_string t1 || is_string t2 then
-						basic.tstring, basic.tstring
-					else if is_double t1 || is_double t2 then
-						basic.tfloat, basic.tfloat
-					else if is_int t1 || is_int t2 then
-						basic.tint, basic.tint
-					else t1, t2 in
-					{ eexpr = TBinop(Ast.OpAdd, mk_cast t1 e1, mk_cast t2 e2); etype = e.etype; epos = e1.epos }
-				| _ when is_string e.etype || is_string e1.etype || is_string e2.etype ->
-					{
-						eexpr = TCall(
-							mk_static_field_access_infer runtime_cl "concat" e.epos [],
-							[ e1; e2 ]
-						);
-						etype = basic.tstring;
-						epos = e.epos
-					}
-				| _ ->
-					let static = mk_static_field_access_infer (runtime_cl) "plus"  e1.epos [] in
-					mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
-		(fun e1 e2 ->
-			if is_string e1.etype then begin
-				{ e1 with eexpr = TCall(mk_static_field_access_infer string_cl "Compare" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint }
-			end else begin
-				let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
-				{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
-			end)
-		~handle_strings:false;
+		let is_undefined e = match e.eexpr with
+			| TLocal { v_name = "__undefined__" } | TField(_,FStatic({cl_path=["haxe";"lang"],"Runtime"},{cf_name="undefined"})) -> true
+			| _ -> false
+		in
 
-	FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);
+		DynamicOperators.configure gen
+			(fun e -> match e.eexpr with
+				| TBinop (Ast.OpEq, e1, e2)
+				| TBinop (Ast.OpNotEq, e1, e2) ->
+					(
+						(* dont touch (v == null) and (null == v) comparisons because they are handled by HardNullableSynf later *)
+						match e1.eexpr, e2.eexpr with
+						| TConst(TNull), _ when (not (is_tparam e2.etype) && is_dynamic e2.etype) || is_null_expr e2 ->
+							false
+						| _, TConst(TNull) when (not (is_tparam e1.etype) && is_dynamic e1.etype) || is_null_expr e1 ->
+							false
+						| _ when is_undefined e1 || is_undefined e2 ->
+							false
+						| _ ->
+							should_handle_opeq e1.etype || should_handle_opeq e2.etype
+					)
+				| TBinop (Ast.OpAssignOp Ast.OpAdd, e1, e2) ->
+					is_dynamic_expr e1 || is_null_expr e1 || is_string e.etype
+				| TBinop (Ast.OpAdd, e1, e2) -> is_dynamic e1.etype || is_dynamic e2.etype || is_tparam e1.etype || is_tparam e2.etype || is_string e1.etype || is_string e2.etype || is_string e.etype
+				| TBinop (Ast.OpLt, e1, e2)
+				| TBinop (Ast.OpLte, e1, e2)
+				| TBinop (Ast.OpGte, e1, e2)
+				| TBinop (Ast.OpGt, e1, e2) -> is_dynamic e.etype || is_dynamic_expr e1 || is_dynamic_expr e2 || is_string e1.etype || is_string e2.etype
+				| TBinop (_, e1, e2) -> is_dynamic e.etype || is_dynamic_expr e1 || is_dynamic_expr e2
+				| TUnop (_, _, e1) -> is_dynamic_expr e1 || is_null_expr e1 (* we will see if the expression is Null<T> also, as the unwrap from Unop will be the same *)
+				| _ -> false)
+			(fun e1 e2 ->
+				let is_basic = is_cs_basic_type (follow e1.etype) || is_cs_basic_type (follow e2.etype) in
+				let is_ref = if is_basic then false else match follow e1.etype, follow e2.etype with
+					| TDynamic _, _
+					| _, TDynamic _
+					| TInst( { cl_path = ([], "String") }, [] ), _
+					| _, TInst( { cl_path = ([], "String") }, [] )
+					| TInst( { cl_kind = KTypeParameter _ }, [] ), _
+					| _, TInst( { cl_kind = KTypeParameter _ }, [] ) -> false
+					| _, _ -> true
+				in
 
-	let base_exception = get_cl (get_type gen (["System"], "Exception")) in
-	let base_exception_t = TInst(base_exception, []) in
+				let static = mk_static_field_access_infer (runtime_cl) (if is_ref then "refEq" else "eq") e1.epos [] in
+				{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tbool; epos=e1.epos }
+			)
+			(fun e e1 e2 ->
+				match may_nullable e1.etype, may_nullable e2.etype with
+					| Some t1, Some t2 ->
+						let t1, t2 = if is_string t1 || is_string t2 then
+							basic.tstring, basic.tstring
+						else if is_double t1 || is_double t2 then
+							basic.tfloat, basic.tfloat
+						else if is_int t1 || is_int t2 then
+							basic.tint, basic.tint
+						else t1, t2 in
+						{ eexpr = TBinop(Ast.OpAdd, mk_cast t1 e1, mk_cast t2 e2); etype = e.etype; epos = e1.epos }
+					| _ when is_string e.etype || is_string e1.etype || is_string e2.etype ->
+						{
+							eexpr = TCall(
+								mk_static_field_access_infer runtime_cl "concat" e.epos [],
+								[ e1; e2 ]
+							);
+							etype = basic.tstring;
+							epos = e.epos
+						}
+					| _ ->
+						let static = mk_static_field_access_infer (runtime_cl) "plus"  e1.epos [] in
+						mk_cast e.etype { eexpr = TCall(static, [e1; e2]); etype = t_dynamic; epos=e1.epos })
+			(fun e1 e2 ->
+				if is_string e1.etype then begin
+					{ e1 with eexpr = TCall(mk_static_field_access_infer string_cl "Compare" e1.epos [], [ e1; e2 ]); etype = gen.gcon.basic.tint }
+				end else begin
+					let static = mk_static_field_access_infer (runtime_cl) "compare" e1.epos [] in
+					{ eexpr = TCall(static, [e1; e2]); etype = gen.gcon.basic.tint; epos=e1.epos }
+				end)
+			~handle_strings:false;
+
+		FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);
+
+		let base_exception = get_cl (get_type gen (["System"], "Exception")) in
+		let base_exception_t = TInst(base_exception, []) in
+
+		let hx_exception = get_cl (get_type gen (["haxe";"lang"], "HaxeException")) in
+		let hx_exception_t = TInst(hx_exception, []) in
+
+		let rec is_exception t =
+			match follow t with
+				| TInst(cl,_) ->
+					if cl == base_exception then
+						true
+					else
+						(match cl.cl_super with | None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
+				| _ -> false
+		in
 
-	let hx_exception = get_cl (get_type gen (["haxe";"lang"], "HaxeException")) in
-	let hx_exception_t = TInst(hx_exception, []) in
+		TryCatchWrapper.configure gen
+			(fun t -> not (is_exception (real_type t)))
+			(fun throwexpr expr ->
+				let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], base_exception_t)) expr.epos in
+				{ throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]); etype = hx_exception_t }; etype = gen.gcon.basic.tvoid }
+			)
+			(fun v_to_unwrap pos ->
+				let local = mk_cast hx_exception_t { eexpr = TLocal(v_to_unwrap); etype = v_to_unwrap.v_type; epos = pos } in
+				mk_field_access gen local "obj" pos
+			)
+			(fun rethrow ->
+				{ rethrow with eexpr = TCall(mk_local (alloc_var "__rethrow__" t_dynamic) rethrow.epos, [rethrow]); etype = gen.gcon.basic.tvoid }
+			)
+			(base_exception_t)
+			(hx_exception_t)
+			(fun v e ->
 
-	let rec is_exception t =
-		match follow t with
-			| TInst(cl,_) ->
-				if cl == base_exception then
-					true
-				else
-					(match cl.cl_super with | None -> false | Some (cl,arg) -> is_exception (TInst(cl,arg)))
-			| _ -> false
-	in
+				let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in
+				let exc_field = mk_static_field_access_infer exc_cl "exception" e.epos [] in
+				let esetstack = mk (TBinop(Ast.OpAssign, exc_field, mk_local v e.epos)) v.v_type e.epos in
 
-	TryCatchWrapper.configure gen
-		(fun t -> not (is_exception (real_type t)))
-		(fun throwexpr expr ->
-			let wrap_static = mk_static_field_access (hx_exception) "wrap" (TFun([("obj",false,t_dynamic)], base_exception_t)) expr.epos in
-			{ throwexpr with eexpr = TThrow { expr with eexpr = TCall(wrap_static, [expr]); etype = hx_exception_t }; etype = gen.gcon.basic.tvoid }
-		)
-		(fun v_to_unwrap pos ->
-			let local = mk_cast hx_exception_t { eexpr = TLocal(v_to_unwrap); etype = v_to_unwrap.v_type; epos = pos } in
-			mk_field_access gen local "obj" pos
-		)
-		(fun rethrow ->
-			{ rethrow with eexpr = TCall(mk_local (alloc_var "__rethrow__" t_dynamic) rethrow.epos, [rethrow]); etype = gen.gcon.basic.tvoid }
-		)
-		(base_exception_t)
-		(hx_exception_t)
-		(fun v e ->
-
-			let exc_cl = get_cl (get_type gen (["haxe";"lang"],"Exceptions")) in
-			let exc_field = mk_static_field_access_infer exc_cl "exception" e.epos [] in
-			let esetstack = mk (TBinop(Ast.OpAssign, exc_field, mk_local v e.epos)) v.v_type e.epos in
-
-			Type.concat esetstack e;
-		);
+				Type.concat esetstack e;
+			);
 
-	ClassInstance.configure gen (fun e _ -> { e with eexpr = TCall({ eexpr = TLocal(alloc_var "__typeof__" t_dynamic); etype = t_dynamic; epos = e.epos }, [e]) });
+		ClassInstance.configure gen (fun e _ -> { e with eexpr = TCall({ eexpr = TLocal(alloc_var "__typeof__" t_dynamic); etype = t_dynamic; epos = e.epos }, [e]) });
 
-	CastDetect.configure gen (Some empty_ctor_type) (not erase_generics) ~overloads_cast_to_base:true;
+		CastDetect.configure gen (Some empty_ctor_type) (not erase_generics) ~overloads_cast_to_base:true;
 
-	SwitchToIf.configure gen (fun e ->
-		match e.eexpr with
-			| TSwitch(cond, cases, def) ->
-				(match gen.gfollow#run_f cond.etype with
-					| TAbstract ({ a_path = ([], "Int") },[])
-					| TInst({ cl_path = ([], "String") },[]) ->
-						(List.exists (fun (c,_) ->
-							List.exists (fun expr -> match expr.eexpr with | TConst _ -> false | _ -> true ) c
-						) cases)
-					| _ -> true
-				)
-			| _ -> assert false
-	);
+		SwitchToIf.configure gen (fun e ->
+			match e.eexpr with
+				| TSwitch(cond, cases, def) ->
+					(match gen.gfollow#run_f cond.etype with
+						| TAbstract ({ a_path = ([], "Int") },[])
+						| TInst({ cl_path = ([], "String") },[]) ->
+							(List.exists (fun (c,_) ->
+								List.exists (fun expr -> match expr.eexpr with | TConst _ -> false | _ -> true ) c
+							) cases)
+						| _ -> true
+					)
+				| _ -> assert false
+		);
 
-	ExpressionUnwrap.configure gen (fun e -> Some { eexpr = TVar(mk_temp "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos });
+		ExpressionUnwrap.configure gen (fun e -> Some { eexpr = TVar(mk_temp "expr" e.etype, Some e); etype = gen.gcon.basic.tvoid; epos = e.epos });
 
-	UnnecessaryCastsRemoval.configure gen;
+		UnnecessaryCastsRemoval.configure gen;
 
-	IntDivisionSynf.configure gen;
+		IntDivisionSynf.configure gen;
 
-	UnreachableCodeEliminationSynf.configure gen false;
+		UnreachableCodeEliminationSynf.configure gen false;
 
-	ArrayDeclSynf.configure gen native_arr_cl;
+		ArrayDeclSynf.configure gen native_arr_cl;
 
-	let goto_special = alloc_var "__goto__" t_dynamic in
-	let label_special = alloc_var "__label__" t_dynamic in
-	SwitchBreakSynf.configure gen
-		(fun e_loop n api ->
-			api ({ eexpr = TCall( mk_local label_special e_loop.epos, [ ExprBuilder.make_int gen.gcon n e_loop.epos ] ); etype = t_dynamic; epos = e_loop.epos }) false;
-			e_loop
-		)
-		(fun e_break n api ->
-			{ eexpr = TCall( mk_local goto_special e_break.epos, [ ExprBuilder.make_int gen.gcon n e_break.epos ] ); etype = t_dynamic; epos = e_break.epos }
-		);
+		let goto_special = alloc_var "__goto__" t_dynamic in
+		let label_special = alloc_var "__label__" t_dynamic in
+		SwitchBreakSynf.configure gen
+			(fun e_loop n api ->
+				api ({ eexpr = TCall( mk_local label_special e_loop.epos, [ ExprBuilder.make_int gen.gcon n e_loop.epos ] ); etype = t_dynamic; epos = e_loop.epos }) false;
+				e_loop
+			)
+			(fun e_break n api ->
+				{ eexpr = TCall( mk_local goto_special e_break.epos, [ ExprBuilder.make_int gen.gcon n e_break.epos ] ); etype = t_dynamic; epos = e_break.epos }
+			);
 
-	DefaultArguments.configure gen;
-	InterfaceMetas.configure gen;
+		DefaultArguments.configure gen;
+		InterfaceMetas.configure gen;
 
-	CSharpSpecificSynf.configure gen runtime_cl;
-	CSharpSpecificESynf.configure gen runtime_cl;
+		CSharpSpecificSynf.configure gen runtime_cl;
+		CSharpSpecificESynf.configure gen runtime_cl;
 
-	let out_files = ref [] in
+		let out_files = ref [] in
 
-	(* copy resource files *)
-	if Hashtbl.length gen.gcon.resources > 0 then begin
-		let src =
-				gen.gcon.file ^ "/src/Resources"
-		in
-		Hashtbl.iter (fun name v ->
-			let name = Codegen.escape_res_name name true in
-			let full_path = src ^ "/" ^ name in
-			mkdir_from_path full_path;
-
-			let f = open_out_bin full_path in
-			output_string f v;
-			close_out f;
-
-			out_files := (Path.unique_full_path full_path) :: !out_files
-		) gen.gcon.resources;
-	end;
-	(* add resources array *)
-	(try
-		let res = get_cl (Hashtbl.find gen.gtypes (["haxe"], "Resource")) in
-		let cf = PMap.find "content" res.cl_statics in
-		let res = ref [] in
-		Hashtbl.iter (fun name v ->
-			res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res;
-		) gen.gcon.resources;
-		cf.cf_expr <- Some ({ eexpr = TArrayDecl(!res); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = null_pos })
-	with | Not_found -> ());
-
-	run_filters gen;
-	(* after the filters have been run, add all hashed fields to FieldLookup *)
-
-	let normalize_i i =
-		let i = Int32.of_int (i) in
-		if i < Int32.zero then
-			Int32.logor (Int32.logand i (Int32.of_int 0x3FFFFFFF)) (Int32.shift_left Int32.one 30)
-		else i
-	in
+		(* copy resource files *)
+		if Hashtbl.length gen.gcon.resources > 0 then begin
+			let src =
+					gen.gcon.file ^ "/src/Resources"
+			in
+			Hashtbl.iter (fun name v ->
+				let name = Codegen.escape_res_name name true in
+				let full_path = src ^ "/" ^ name in
+				mkdir_from_path full_path;
 
-	let nhash = ref 0 in
-	let hashes = Hashtbl.fold (fun i s acc -> incr nhash; (normalize_i i,s) :: acc) rcf_ctx.rcf_hash_fields [] in
-	let hashes = List.sort (fun (i,s) (i2,s2) -> compare i i2) hashes in
+				let f = open_out_bin full_path in
+				output_string f v;
+				close_out f;
 
-	let haxe_libs = List.filter (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "DceNo"))) gen.gcon.net_libs in
-	(try
-		(* first let's see if we're adding a -net-lib that has already a haxe.lang.FieldLookup *)
-		let name,_,_,_ = List.find (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "FieldLookup"))) gen.gcon.net_libs in
-		if not (Common.defined gen.gcon Define.DllImport) then begin
-			gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly. Please define `-D dll_import` to handle Haxe-generated dll import correctly") null_pos;
-			raise Not_found
+				out_files := (Path.unique_full_path full_path) :: !out_files
+			) gen.gcon.resources;
 		end;
-		if not (List.exists (function (n,_,_,_) -> n = name) haxe_libs) then
-			gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly, however it wasn't compiled with `-dce no`. Recompilation with `-dce no` is recommended") null_pos;
-		(* it has; in this case, we need to add the used fields on each __init__ *)
-		flookup_cl.cl_extern <- true;
-		let hashs_by_path = Hashtbl.create !nhash in
-		Hashtbl.iter (fun (path,i) s -> Hashtbl.add hashs_by_path path (i,s)) rcf_ctx.rcf_hash_paths;
-		Hashtbl.iter (fun _ md -> match md with
-			| TClassDecl ({ cl_extern = false; cl_interface = false } as c) -> (try
-				let all = Hashtbl.find_all hashs_by_path c.cl_path in
-				let all = List.map (fun (i,s) -> normalize_i i, s) all in
-				let all = List.sort (fun (i,s) (i2,s2) -> compare i i2) all in
-
-				if all <> [] then begin
-					let add = mk_static_field_access_infer flookup_cl "addFields" c.cl_pos [] in
-					let expr = { eexpr = TCall(add, [
-						mk_nativearray_decl gen basic.tint (List.map (fun (i,s) -> { eexpr = TConst(TInt (i)); etype = basic.tint; epos = c.cl_pos }) all) c.cl_pos;
-						mk_nativearray_decl gen basic.tstring (List.map (fun (i,s) -> { eexpr = TConst(TString (s)); etype = basic.tstring; epos = c.cl_pos }) all) c.cl_pos;
-					]); etype = basic.tvoid; epos = c.cl_pos } in
-					match c.cl_init with
-						| None -> c.cl_init <- Some expr
-						| Some e ->
-							c.cl_init <- Some { eexpr = TBlock([expr;e]); etype = basic.tvoid; epos = e.epos }
-				end
-			with | Not_found -> ())
-			| _ -> ()) gen.gtypes;
-
-	with | Not_found -> try
-		let basic = gen.gcon.basic in
-		let cl = flookup_cl in
-		let field_ids = PMap.find "fieldIds" cl.cl_statics in
-		let fields = PMap.find "fields" cl.cl_statics in
-
-		field_ids.cf_expr <- Some (mk_nativearray_decl gen basic.tint (List.map (fun (i,s) -> { eexpr = TConst(TInt (i)); etype = basic.tint; epos = field_ids.cf_pos }) hashes) field_ids.cf_pos);
-		fields.cf_expr <- Some (mk_nativearray_decl gen basic.tstring (List.map (fun (i,s) -> { eexpr = TConst(TString s); etype = basic.tstring; epos = fields.cf_pos }) hashes) fields.cf_pos);
-
-	with | Not_found ->
-		gen.gcon.error "Fields 'fieldIds' and 'fields' were not found in class haxe.lang.FieldLookup" flookup_cl.cl_pos
-	);
-
-	if Common.defined gen.gcon Define.DllImport then begin
-		Hashtbl.iter (fun _ md -> match md with
-			| TClassDecl ({ cl_extern = false } as c) -> (try
-				let extra = match c.cl_params with
-					| _ :: _ when not erase_generics -> "_" ^ string_of_int (List.length c.cl_params)
-					| _ -> ""
-				in
-				let pack = match c.cl_path with
-					| ([], _) when no_root && is_hxgen (TClassDecl c) ->
-						["haxe";"root"]
-					| (p,_) -> p
-				in
-				let path = (pack, snd c.cl_path ^ extra) in
-				ignore (List.find (function (_,_,_,lookup) ->
-					is_some (lookup path)) haxe_libs);
-				c.cl_extern <- true;
-			with | Not_found -> ())
-			| _ -> ()) gen.gtypes
-	end;
-
-	TypeParams.RenameTypeParameters.run gen;
-
-	let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in
-	mkdir_recursive "" parts;
-
-	List.iter (fun md_def ->
-		let source_dir = gen.gcon.file ^ "/src/" ^ (String.concat "/" (fst (path_of_md_def md_def))) in
-		let w = SourceWriter.new_source_writer() in
-		let should_write = List.fold_left (fun should md -> module_type_gen w md || should) false md_def.m_types in
-		if should_write then begin
-			let path = path_of_md_def md_def in
-			write_file gen w source_dir path "cs" out_files
-		end
-	) gen.gmodules;
+		(* add resources array *)
+		(try
+			let res = get_cl (Hashtbl.find gen.gtypes (["haxe"], "Resource")) in
+			let cf = PMap.find "content" res.cl_statics in
+			let res = ref [] in
+			Hashtbl.iter (fun name v ->
+				res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res;
+			) gen.gcon.resources;
+			cf.cf_expr <- Some ({ eexpr = TArrayDecl(!res); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = null_pos })
+		with | Not_found -> ());
 
-	if not (Common.defined gen.gcon Define.KeepOldOutput) then
-		clean_files (gen.gcon.file ^ "/src") !out_files gen.gcon.verbose;
+		run_filters gen;
+		(* after the filters have been run, add all hashed fields to FieldLookup *)
 
-	dump_descriptor gen ("hxcs_build.txt") s_type_path module_s;
-	if ( not (Common.defined gen.gcon Define.NoCompilation) ) then begin
-		let old_dir = Sys.getcwd() in
-		Sys.chdir gen.gcon.file;
-		let cmd = "haxelib run hxcs hxcs_build.txt --haxe-version " ^ (string_of_int gen.gcon.version) ^ " --feature-level 1" in
-		print_endline cmd;
-		if gen.gcon.run_command cmd <> 0 then failwith "Build failed";
-		Sys.chdir old_dir;
-	end
+		let normalize_i i =
+			let i = Int32.of_int (i) in
+			if i < Int32.zero then
+				Int32.logor (Int32.logand i (Int32.of_int 0x3FFFFFFF)) (Int32.shift_left Int32.one 30)
+			else i
+		in
 
-(* end of configure function *)
+		let nhash = ref 0 in
+		let hashes = Hashtbl.fold (fun i s acc -> incr nhash; (normalize_i i,s) :: acc) rcf_ctx.rcf_hash_fields [] in
+		let hashes = List.sort (fun (i,s) (i2,s2) -> compare i i2) hashes in
 
-let generate con =
-	(try
+		let haxe_libs = List.filter (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "DceNo"))) gen.gcon.net_libs in
+		(try
+			(* first let's see if we're adding a -net-lib that has already a haxe.lang.FieldLookup *)
+			let name,_,_,_ = List.find (function (_,_,_,lookup) -> is_some (lookup (["haxe";"lang"], "FieldLookup"))) gen.gcon.net_libs in
+			if not (Common.defined gen.gcon Define.DllImport) then begin
+				gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly. Please define `-D dll_import` to handle Haxe-generated dll import correctly") null_pos;
+				raise Not_found
+			end;
+			if not (List.exists (function (n,_,_,_) -> n = name) haxe_libs) then
+				gen.gcon.warning ("The -net-lib with path " ^ name ^ " contains a Haxe-generated assembly, however it wasn't compiled with `-dce no`. Recompilation with `-dce no` is recommended") null_pos;
+			(* it has; in this case, we need to add the used fields on each __init__ *)
+			flookup_cl.cl_extern <- true;
+			let hashs_by_path = Hashtbl.create !nhash in
+			Hashtbl.iter (fun (path,i) s -> Hashtbl.add hashs_by_path path (i,s)) rcf_ctx.rcf_hash_paths;
+			Hashtbl.iter (fun _ md -> match md with
+				| TClassDecl ({ cl_extern = false; cl_interface = false } as c) -> (try
+					let all = Hashtbl.find_all hashs_by_path c.cl_path in
+					let all = List.map (fun (i,s) -> normalize_i i, s) all in
+					let all = List.sort (fun (i,s) (i2,s2) -> compare i i2) all in
+
+					if all <> [] then begin
+						let add = mk_static_field_access_infer flookup_cl "addFields" c.cl_pos [] in
+						let expr = { eexpr = TCall(add, [
+							mk_nativearray_decl gen basic.tint (List.map (fun (i,s) -> { eexpr = TConst(TInt (i)); etype = basic.tint; epos = c.cl_pos }) all) c.cl_pos;
+							mk_nativearray_decl gen basic.tstring (List.map (fun (i,s) -> { eexpr = TConst(TString (s)); etype = basic.tstring; epos = c.cl_pos }) all) c.cl_pos;
+						]); etype = basic.tvoid; epos = c.cl_pos } in
+						match c.cl_init with
+							| None -> c.cl_init <- Some expr
+							| Some e ->
+								c.cl_init <- Some { eexpr = TBlock([expr;e]); etype = basic.tvoid; epos = e.epos }
+					end
+				with | Not_found -> ())
+				| _ -> ()) gen.gtypes;
+
+		with | Not_found -> try
+			let basic = gen.gcon.basic in
+			let cl = flookup_cl in
+			let field_ids = PMap.find "fieldIds" cl.cl_statics in
+			let fields = PMap.find "fields" cl.cl_statics in
+
+			field_ids.cf_expr <- Some (mk_nativearray_decl gen basic.tint (List.map (fun (i,s) -> { eexpr = TConst(TInt (i)); etype = basic.tint; epos = field_ids.cf_pos }) hashes) field_ids.cf_pos);
+			fields.cf_expr <- Some (mk_nativearray_decl gen basic.tstring (List.map (fun (i,s) -> { eexpr = TConst(TString s); etype = basic.tstring; epos = fields.cf_pos }) hashes) fields.cf_pos);
 
-		let gen = new_ctx con in
-		let basic = con.basic in
+		with | Not_found ->
+			gen.gcon.error "Fields 'fieldIds' and 'fields' were not found in class haxe.lang.FieldLookup" flookup_cl.cl_pos
+		);
 
-		if Common.defined_value con Define.Dce = "no" then begin
-			let m = { null_module with m_id = alloc_mid(); m_path = ["haxe";"lang"],"DceNo" } in
-			let cl = mk_class m (["haxe";"lang"],"DceNo") null_pos in
-			gen.gtypes_list <- (TClassDecl cl) :: gen.gtypes_list;
-			Hashtbl.add gen.gtypes cl.cl_path (TClassDecl cl)
+		if Common.defined gen.gcon Define.DllImport then begin
+			Hashtbl.iter (fun _ md -> match md with
+				| TClassDecl ({ cl_extern = false } as c) -> (try
+					let extra = match c.cl_params with
+						| _ :: _ when not erase_generics -> "_" ^ string_of_int (List.length c.cl_params)
+						| _ -> ""
+					in
+					let pack = match c.cl_path with
+						| ([], _) when no_root && is_hxgen (TClassDecl c) ->
+							["haxe";"root"]
+						| (p,_) -> p
+					in
+					let path = (pack, snd c.cl_path ^ extra) in
+					ignore (List.find (function (_,_,_,lookup) ->
+						is_some (lookup path)) haxe_libs);
+					c.cl_extern <- true;
+				with | Not_found -> ())
+				| _ -> ()) gen.gtypes
 		end;
 
-		(* make the basic functions in C# *)
-		let type_cl = get_cl ( get_type gen (["System"], "Type")) in
-		let basic_fns =
-		[
-			mk_class_field "Equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true null_pos (Method MethNormal) [];
-			mk_class_field "ToString" (TFun([], basic.tstring)) true null_pos (Method MethNormal) [];
-			mk_class_field "GetHashCode" (TFun([], basic.tint)) true null_pos (Method MethNormal) [];
-			mk_class_field "GetType" (TFun([], TInst(type_cl, []))) true null_pos (Method MethNormal) [];
-		] in
-		List.iter (fun cf -> gen.gbase_class_fields <- PMap.add cf.cf_name cf gen.gbase_class_fields) basic_fns;
-		configure gen
-	with | TypeNotFound path ->
-		con.error ("Error. Module '" ^ (s_type_path path) ^ "' is required and was not included in build.")	null_pos);
+		TypeParams.RenameTypeParameters.run gen;
+
+		let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in
+		mkdir_recursive "" parts;
+
+		List.iter (fun md_def ->
+			let source_dir = gen.gcon.file ^ "/src/" ^ (String.concat "/" (fst (path_of_md_def md_def))) in
+			let w = SourceWriter.new_source_writer() in
+			let should_write = List.fold_left (fun should md -> module_type_gen w md || should) false md_def.m_types in
+			if should_write then begin
+				let path = path_of_md_def md_def in
+				write_file gen w source_dir path "cs" out_files
+			end
+		) gen.gmodules;
+
+		if not (Common.defined gen.gcon Define.KeepOldOutput) then
+			clean_files (gen.gcon.file ^ "/src") !out_files gen.gcon.verbose;
+
+		dump_descriptor gen ("hxcs_build.txt") s_type_path module_s;
+		if ( not (Common.defined gen.gcon Define.NoCompilation) ) then begin
+			let old_dir = Sys.getcwd() in
+			Sys.chdir gen.gcon.file;
+			let cmd = "haxelib run hxcs hxcs_build.txt --haxe-version " ^ (string_of_int gen.gcon.version) ^ " --feature-level 1" in
+			print_endline cmd;
+			if gen.gcon.run_command cmd <> 0 then failwith "Build failed";
+			Sys.chdir old_dir;
+		end
+
+	with TypeNotFound path ->
+		con.error ("Error. Module '" ^ (s_type_path path) ^ "' is required and was not included in build.") null_pos);
 	debug_mode := false

+ 30 - 38
src/generators/genjava.ml

@@ -805,16 +805,40 @@ let rec get_fun_modifiers meta access modifiers =
 		| (Meta.Native,[],_) :: meta -> get_fun_modifiers meta access ("native" :: modifiers)
 		| _ :: meta -> get_fun_modifiers meta access modifiers
 
-(* this was the way I found to pass the generator context to be accessible across all functions here *)
-(* so 'configure' is almost 'top-level' and will have all functions needed to make this work *)
-let configure gen =
+let generate con =
+	let exists = ref false in
+	con.java_libs <- List.map (fun (file,std,close,la,gr) ->
+		if String.ends_with file "hxjava-std.jar" then begin
+			exists := true;
+			(file,true,close,la,gr)
+		end else
+			(file,std,close,la,gr)) con.java_libs;
+	if not !exists then
+		failwith "Your version of hxjava is outdated. Please update it by running: `haxelib update hxjava`";
+	let gen = new_ctx con in
+	gen.gallow_tp_dynamic_conversion <- true;
+
+	let basic = con.basic in
+	(* make the basic functions in java *)
+	let cl_cl = get_cl (get_type gen (["java";"lang"],"Class")) in
+	let basic_fns =
+	[
+		mk_class_field "equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true null_pos (Method MethNormal) [];
+		mk_class_field "toString" (TFun([], basic.tstring)) true null_pos (Method MethNormal) [];
+		mk_class_field "hashCode" (TFun([], basic.tint)) true null_pos (Method MethNormal) [];
+		mk_class_field "getClass" (TFun([], (TInst(cl_cl,[t_dynamic])))) true null_pos (Method MethNormal) [];
+		mk_class_field "wait" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) [];
+		mk_class_field "notify" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) [];
+		mk_class_field "notifyAll" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) [];
+	] in
+	List.iter (fun cf -> gen.gbase_class_fields <- PMap.add cf.cf_name cf gen.gbase_class_fields) basic_fns;
+
+	(try
 	let native_arr_cl = get_cl ( get_type gen (["java"], "NativeArray") ) in
 	gen.gclasses.nativearray <- (fun t -> TInst(native_arr_cl,[t]));
 	gen.gclasses.nativearray_type <- (function TInst(_,[t]) -> t | _ -> assert false);
 	gen.gclasses.nativearray_len <- (fun e p -> mk_field_access gen e "length" p);
 
-	let basic = gen.gcon.basic in
-
 	let fn_cl = get_cl (get_type gen (["haxe";"lang"],"Function")) in
 
 	let runtime_cl = get_cl (get_type gen (["haxe";"lang"],"Runtime")) in
@@ -2463,37 +2487,5 @@ let configure gen =
 		Sys.chdir old_dir;
 	end
 
-(* end of configure function *)
-
-let generate con =
-	let exists = ref false in
-	con.java_libs <- List.map (fun (file,std,close,la,gr) ->
-		if String.ends_with file "hxjava-std.jar" then begin
-			exists := true;
-			(file,true,close,la,gr)
-		end else
-			(file,std,close,la,gr)) con.java_libs;
-	if not !exists then
-		failwith "Your version of hxjava is outdated. Please update it by running: `haxelib update hxjava`";
-	let gen = new_ctx con in
-	gen.gallow_tp_dynamic_conversion <- true;
-
-	let basic = con.basic in
-	(* make the basic functions in java *)
-	let cl_cl = get_cl (get_type gen (["java";"lang"],"Class")) in
-	let basic_fns =
-	[
-		mk_class_field "equals" (TFun(["obj",false,t_dynamic], basic.tbool)) true null_pos (Method MethNormal) [];
-		mk_class_field "toString" (TFun([], basic.tstring)) true null_pos (Method MethNormal) [];
-		mk_class_field "hashCode" (TFun([], basic.tint)) true null_pos (Method MethNormal) [];
-		mk_class_field "getClass" (TFun([], (TInst(cl_cl,[t_dynamic])))) true null_pos (Method MethNormal) [];
-		mk_class_field "wait" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) [];
-		mk_class_field "notify" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) [];
-		mk_class_field "notifyAll" (TFun([], basic.tvoid)) true null_pos (Method MethNormal) [];
-	] in
-	List.iter (fun cf -> gen.gbase_class_fields <- PMap.add cf.cf_name cf gen.gbase_class_fields) basic_fns;
-
-	(try
-		configure gen
-	with | TypeNotFound path -> con.error ("Error. Module '" ^ (s_type_path path) ^ "' is required and was not included in build.")	null_pos);
+	with TypeNotFound path -> con.error ("Error. Module '" ^ (s_type_path path) ^ "' is required and was not included in build.") null_pos);
 	debug_mode := false