ソースを参照

remove generators and gencommon

Simon Krajewski 2 年 前
コミット
456fb4a899
35 ファイル変更20 行追加16809 行削除
  1. 0 43
      src/codegen/gencommon/abstractImplementationFix.ml
  2. 0 51
      src/codegen/gencommon/arrayDeclSynf.ml
  3. 0 40
      src/codegen/gencommon/arraySpliceOptimization.ml
  4. 0 1341
      src/codegen/gencommon/castDetect.ml
  5. 0 57
      src/codegen/gencommon/classInstance.ml
  6. 0 1184
      src/codegen/gencommon/closuresToClass.ml
  7. 0 132
      src/codegen/gencommon/dynamicFieldAccess.ml
  8. 0 190
      src/codegen/gencommon/dynamicOperators.ml
  9. 0 302
      src/codegen/gencommon/enumToClass.ml
  10. 0 399
      src/codegen/gencommon/enumToClass2.ml
  11. 0 638
      src/codegen/gencommon/expressionUnwrap.ml
  12. 0 86
      src/codegen/gencommon/filterClosures.ml
  13. 0 276
      src/codegen/gencommon/fixOverrides.ml
  14. 0 1365
      src/codegen/gencommon/gencommon.ml
  15. 0 284
      src/codegen/gencommon/hardNullableSynf.ml
  16. 0 239
      src/codegen/gencommon/initFunction.ml
  17. 0 86
      src/codegen/gencommon/intDivisionSynf.ml
  18. 0 43
      src/codegen/gencommon/interfaceProps.ml
  19. 0 84
      src/codegen/gencommon/interfaceVarsDeleteModf.ml
  20. 0 100
      src/codegen/gencommon/normalize.ml
  21. 0 37
      src/codegen/gencommon/objectDeclMap.ml
  22. 0 460
      src/codegen/gencommon/overloadingConstructor.ml
  23. 0 784
      src/codegen/gencommon/realTypeParams.ml
  24. 0 1536
      src/codegen/gencommon/reflectionCFs.ml
  25. 0 101
      src/codegen/gencommon/renameTypeParameters.ml
  26. 0 101
      src/codegen/gencommon/setHXGen.ml
  27. 0 162
      src/codegen/gencommon/switchToIf.ml
  28. 0 104
      src/codegen/gencommon/tArrayTransform.ml
  29. 0 60
      src/codegen/gencommon/unnecessaryCastsRemoval.ml
  30. 0 212
      src/codegen/gencommon/unreachableCodeEliminationSynf.ml
  31. 3 6
      src/compiler/generate.ml
  32. 0 14
      src/filters/filters.ml
  33. 0 3568
      src/generators/gencs.ml
  34. 0 2723
      src/generators/genjava.ml
  35. 17 1
      src/generators/genshared.ml

+ 0 - 43
src/codegen/gencommon/abstractImplementationFix.ml

@@ -1,43 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Type
-open Gencommon
-
-(** add abstract type parameters to abstract implementation methods *)
-let add_abstract_params = function
-	| TClassDecl ({ cl_kind = KAbstractImpl a } as c) ->
-		List.iter (
-			function
-			| ({ cf_name = "_new" } as cf) ->
-				cf.cf_params <- cf.cf_params @ a.a_params
-			| cf when has_class_field_flag cf CfImpl ->
-				(match cf.cf_expr with
-				| Some({ eexpr = TFunction({ tf_args = (v, _) :: _ }) }) when Meta.has Meta.This v.v_meta ->
-					cf.cf_params <- cf.cf_params @ a.a_params
-				| _ -> ())
-			| _ -> ()
-		) c.cl_ordered_statics
-	| _ -> ()
-
-let name = "abstract_implementation_fix"
-let priority = solve_deps name []
-
-let configure gen =
-	let run md = (add_abstract_params md; md) in
-	gen.gmodule_filters#add name (PCustom priority) run

+ 0 - 51
src/codegen/gencommon/arrayDeclSynf.ml

@@ -1,51 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Type
-open Gencommon
-
-(*
-	A syntax filter that will change array declarations to the actual native array declarations plus
-	the haxe array initialization
-
-	dependencies:
-		Must run after ObjectDeclMap since it can add TArrayDecl expressions
-*)
-let init (native_array_cl : tclass) (change_type_params : module_type -> t list -> t list) =
-	let rec run e =
-		match e.eexpr with
-		| TArrayDecl el ->
-			let cl, params = match follow e.etype with
-				| TInst(({ cl_path = ([], "Array") } as cl), ( _ :: _  as params)) -> cl, params
-				| TInst(({ cl_path = ([], "Array") } as cl), []) -> cl, [t_dynamic]
-				| _ -> Globals.die "" __LOC__
-			in
-			let params = change_type_params (TClassDecl cl) params in
-			let e_inner_decl = mk (TArrayDecl (List.map run el)) (TInst (native_array_cl, params)) e.epos in
-			mk (TNew (cl, params, [e_inner_decl])) e.etype e.epos
-		| _ ->
-			Type.map_expr run e
-	in
-	run
-
-let name = "array_decl_synf"
-let priority = solve_deps name [DAfter ObjectDeclMap.priority]
-
-let configure gen native_array_cl change_type_params =
-	let run = init native_array_cl change_type_params in
-	gen.gsyntax_filters#add name (PCustom priority) run

+ 0 - 40
src/codegen/gencommon/arraySpliceOptimization.ml

@@ -1,40 +0,0 @@
-open Common
-open Type
-open Gencommon
-
-(*
-	This filter finds lone array.splice(...) calls within blocks
-	and replaces them with array.spliceVoid(...) calls
-	that don't allocate additional array for removed items.
-*)
-let init com =
-	let rec run e =
-		match e.eexpr with
-		| TBlock el ->
-			let el = List.map (fun e ->
-				match e.eexpr with
-				| TCall ({ eexpr = TField (eobj, FInstance ({ cl_path = [],"Array" } as cl, params, { cf_name = "splice" })) } as e_splice, args) ->
-					let f_spliceVoid = PMap.find "spliceVoid" cl.cl_fields in
-					let e_spliceVoid = { e_splice with
-						eexpr = TField (eobj, FInstance (cl, params, f_spliceVoid));
-						etype = f_spliceVoid.cf_type;
-					} in
-					{ e with
-						eexpr = TCall (e_spliceVoid, args);
-						etype = com.basic.tvoid;
-					}
-				| _ ->
-					run e
-			) el in
-			{ e with eexpr = TBlock el }
-		| _ ->
-			Type.map_expr run e
-	in
-	run
-
-let name = "array_splice_synf"
-let priority = solve_deps name [DAfter ExpressionUnwrap.priority]
-
-let configure gen =
-	let run = init gen.gcon in
-	gen.gsyntax_filters#add name (PCustom priority) run

+ 0 - 1341
src/codegen/gencommon/castDetect.ml

@@ -1,1341 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Common
-open Ast
-open Globals
-open Type
-open Codegen
-open Gencommon
-
-(* ******************************************* *)
-(* Casts detection v2 *)
-(* ******************************************* *)
-(*
-	Will detect implicit casts and add TCast for them. Since everything is already followed by follow_all, typedefs are considered a new type altogether
-
-	Types shouldn't be cast if:
-		* When an instance is being coerced to a superclass or to an implemented interface
-		* When anything is being coerced to Dynamic
-
-	edit:
-		As a matter of performance, we will also run the type parameters casts in here. Otherwise the exact same computation would have to be performed twice,
-		with maybe even some loss of information
-
-		* TAnon / TDynamic will call
-		* Type parameter handling will be abstracted
-
-	dependencies:
-		Must run before ExpressionUnwrap
-
-*)
-let name = "cast_detect"
-let priority = solve_deps name [DBefore RealTypeParams.priority; DBefore ExpressionUnwrap.priority]
-
-(* ******************************************* *)
-(* ReturnCast *)
-(* ******************************************* *)
-(*
-	Cast detection for return types can't be done at CastDetect time, since we need an
-	unwrapped expression to make sure we catch all return cast detections. So this module
-	is specifically to deal with that, and is configured automatically by CastDetect
-*)
-module ReturnCast =
-struct
-	let name = "return_cast"
-	let priority = solve_deps name [DAfter priority; DAfter ExpressionUnwrap.priority]
-
-	let default_implementation gen =
-		let rec extract_expr e = match e.eexpr with
-			| TParenthesis e
-			| TMeta (_,e)
-			| TCast(e,_) -> extract_expr e
-			| _ -> e
-		in
-		let current_ret_type = ref None in
-		let handle e tto tfrom = gen.ghandle_cast (gen.greal_type tto) (gen.greal_type tfrom) e in
-		let in_value = ref false in
-		let binop_right_expr_type op actual_type =
-			match op with
-			| OpShr | OpShl | OpUShr | OpAssignOp (OpShr | OpShl | OpUShr) ->
-				(match follow actual_type with
-				| TAbstract ({ a_path = (["cs"], "Int64") }, _) -> gen.gcon.basic.tint
-				| _ -> actual_type)
-			| _ -> actual_type
-		in
-
-		let rec run e =
-			let was_in_value = !in_value in
-			in_value := true;
-			match e.eexpr with
-			| TReturn (eopt) ->
-				(* a return must be inside a function *)
-				let ret_type = match !current_ret_type with | Some(s) -> s | None -> gen.gcon.error "Invalid return outside function declaration." e.epos; die "" __LOC__ in
-				(match eopt with
-				| None when not (ExtType.is_void ret_type) ->
-					Texpr.Builder.mk_return (null ret_type e.epos)
-				| None -> e
-				| Some eret ->
-					Texpr.Builder.mk_return (handle (run eret) ret_type eret.etype))
-			| TFunction(tfunc) ->
-				let last_ret = !current_ret_type in
-				current_ret_type := Some(tfunc.tf_type);
-				let ret = Type.map_expr run e in
-				current_ret_type := last_ret;
-				ret
-			| TBlock el ->
-				{ e with eexpr = TBlock ( List.map (fun e -> in_value := false; run e) el ) }
-			| TBinop ( (Ast.OpAssign as op),e1,e2)
-			| TBinop ( (Ast.OpAssignOp _ as op),e1,e2) when was_in_value ->
-				let e1 = extract_expr (run e1) in
-				let r = { e with eexpr = TBinop(op, e1, handle (run e2) e1.etype e2.etype); etype = e1.etype } in
-				handle r e.etype e1.etype
-			| TBinop ( (Ast.OpAssign as op),({ eexpr = TField(tf, f) } as e1), e2 )
-			| TBinop ( (Ast.OpAssignOp _ as op),({ eexpr = TField(tf, f) } as e1), e2 ) ->
-				(match field_access_esp gen (gen.greal_type tf.etype) (f) with
-					| FClassField(cl,params,_,_,is_static,actual_t,_) ->
-						let actual_t = if is_static then actual_t else apply_params cl.cl_params params actual_t in
-						let actual_t = binop_right_expr_type op actual_t in
-						let e1 = extract_expr (run e1) in
-						{ e with eexpr = TBinop(op, e1, handle (run e2) actual_t e2.etype); etype = e1.etype }
-					| _ ->
-						let e1 = extract_expr (run e1) in
-						let actual_t = binop_right_expr_type op e2.etype in
-						{ e with eexpr = TBinop(op, e1, handle (run e2) e1.etype actual_t); etype = e1.etype }
-				)
-			| TBinop ( (Ast.OpAssign as op),e1,e2)
-			| TBinop ( (Ast.OpAssignOp _ as op),e1,e2) ->
-				let e1 = extract_expr (run e1) in
-				let actual_t = binop_right_expr_type op e2.etype in
-				{ e with eexpr = TBinop(op, e1, handle (run e2) e1.etype actual_t); etype = e1.etype }
-			| _ -> Type.map_expr run e
-		in
-		run
-
-	let configure gen =
-		let map = default_implementation gen in
-		gen.gsyntax_filters#add name (PCustom priority) map
-end;;
-
-(*
-	Since this function is applied under native-context only, the type paraters will already be changed
-*)
-let map_cls gen also_implements fn super =
-	let rec loop c tl =
-		if c == super then
-			fn c tl
-		else
-			(match c.cl_super with
-				| None -> false
-				| Some (cs,tls) ->
-					let tls = gen.greal_type_param (TClassDecl cs) tls in
-					loop cs (List.map (apply_params c.cl_params tl) tls)
-			)
-			||
-			(if also_implements then
-				List.exists (fun (cs,tls) -> loop cs (List.map (apply_params c.cl_params tl) tls)) c.cl_implements
-			else
-				false)
-	in
-	loop
-
-let follow_dyn t = match follow t with
-	| TMono _ | TLazy _ -> t_dynamic
-	| t -> t
-
-(*
-	this has a slight change from the type.ml version, in which it doesn't
-	change a TMono into the other parameter
-*)
-let rec type_eq gen param a b =
-	if a == b then
-		()
-	else match follow_dyn (gen.greal_type a) , follow_dyn (gen.greal_type b) with
-	| TEnum (e1,tl1) , TEnum (e2,tl2) ->
-		if e1 != e2 && not (param = EqCoreType && e1.e_path = e2.e_path) then Type.error [cannot_unify a b];
-		List.iter2 (type_eq gen param) tl1 tl2
-	| TAbstract (a1,tl1) , TAbstract (a2,tl2) ->
-		if a1 != a2 && not (param = EqCoreType && a1.a_path = a2.a_path) then Type.error [cannot_unify a b];
-		List.iter2 (type_eq gen param) tl1 tl2
-	| TInst (c1,tl1) , TInst (c2,tl2) ->
-		if c1 != c2 && not (param = EqCoreType && c1.cl_path = c2.cl_path) && (match c1.cl_kind, c2.cl_kind with KExpr _, KExpr _ -> false | _ -> true) then Type.error [cannot_unify a b];
-		List.iter2 (type_eq gen param) tl1 tl2
-	| TFun (l1,r1) , TFun (l2,r2) when List.length l1 = List.length l2 ->
-		(try
-			type_eq gen param r1 r2;
-			List.iter2 (fun (n,o1,t1) (_,o2,t2) ->
-				if o1 <> o2 then Type.error [Not_matching_optional n];
-				type_eq gen param t1 t2
-			) l1 l2
-		with
-			Unify_error l -> Type.error (cannot_unify a b :: l))
-	| TDynamic None , TDynamic None ->
-		()
-	| TDynamic (Some a) , TDynamic (Some b) ->
-		type_eq gen param a b
-	| TAnon a1, TAnon a2 ->
-		(try
-			PMap.iter (fun n f1 ->
-				try
-					let f2 = PMap.find n a2.a_fields in
-					if f1.cf_kind <> f2.cf_kind && (param = EqStrict || param = EqCoreType || not (unify_kind f1.cf_kind f2.cf_kind)) then Type.error [invalid_kind n f1.cf_kind f2.cf_kind];
-					try
-						type_eq gen param f1.cf_type f2.cf_type
-					with
-						Unify_error l -> Type.error (invalid_field n :: l)
-				with
-					Not_found ->
-						Type.error [has_no_field b n];
-			) a1.a_fields;
-			PMap.iter (fun n f2 ->
-				if not (PMap.mem n a1.a_fields) then begin
-					Type.error [has_no_field a n];
-				end;
-			) a2.a_fields;
-		with
-			Unify_error l -> Type.error (cannot_unify a b :: l))
-	| _ , _ ->
-		if b == t_dynamic && (param = EqRightDynamic || param = EqBothDynamic) then
-			()
-		else if a == t_dynamic && param = EqBothDynamic then
-			()
-		else
-			Type.error [cannot_unify a b]
-
-let type_iseq gen a b =
-	try
-		type_eq gen EqStrict a b;
-		true
-	with
-		Unify_error _ -> false
-
-(* will return true if both arguments are compatible. If it's not the case, a runtime error is very likely *)
-let is_cl_related gen cl tl super superl =
-	let is_cl_related cl tl super superl = map_cls gen (match cl.cl_kind,super.cl_kind with KTypeParameter _, _ | _,KTypeParameter _ -> false | _ -> true) (fun _ _ -> true) super cl tl in
-	is_cl_related cl tl super superl || is_cl_related super superl cl tl
-
-let is_exactly_basic gen t1 t2 =
-	match gen.gfollow#run_f t1, gen.gfollow#run_f t2 with
-		| TAbstract(a1, []), TAbstract(a2, []) ->
-			a1 == a2 && Common.defined gen.gcon Define.FastCast
-		| TInst(c1, []), TInst(c2, []) ->
-			c1 == c2 && Common.defined gen.gcon Define.FastCast
-		| TEnum(e1, []), TEnum(e2, []) ->
-			e1 == e2 && Common.defined gen.gcon Define.FastCast
-		| _ ->
-			false
-
-let rec is_unsafe_cast gen to_t from_t =
-	match (follow to_t, follow from_t) with
-		| TInst(cl_to, to_params), TInst(cl_from, from_params) ->
-			not (is_cl_related gen cl_from from_params cl_to to_params)
-		| TEnum(e_to, _), TEnum(e_from, _) ->
-			e_to.e_path <> e_from.e_path
-		| TFun _, TFun _ ->
-			(* functions are never unsafe cast by default. This behavior might be changed *)
-			(* with a later AST pass which will run through TFun to TFun casts *)
-			false
-		| TMono _, _
-		| _, TMono _
-		| TDynamic _, _
-		| _, TDynamic _ ->
-			false
-		| TAnon _, _
-		| _, TAnon _ ->
-			(* anonymous are never unsafe also. *)
-			(* Though they will generate a cast, so if this cast is unneeded it's better to avoid them by tweaking gen.greal_type *)
-			false
-		| TAbstract _, _
-		| _, TAbstract _ ->
-			(try
-				unify from_t to_t;
-				false
-			with | Unify_error _ ->
-				try
-					unify to_t from_t; (* still not unsafe *)
-					false
-				with | Unify_error _ ->
-					true)
-		| _ -> true
-
-let unifies tfrom tto = try
-	unify tfrom tto;
-	true
-with | _ ->
-	false
-
-let do_unsafe_cast gen from_t to_t e	=
-	let t_path t =
-		match t with
-			| TInst(cl, _) -> cl.cl_path
-			| TEnum(e, _) -> e.e_path
-			| TType(t, _) -> t.t_path
-			| TAbstract(a, _) -> a.a_path
-			| TDynamic _ -> ([], "Dynamic")
-			| _ -> raise Not_found
-	in
-	match gen.gfollow#run_f from_t, gen.gfollow#run_f to_t with
-	| TInst({ cl_kind = KTypeParameter tl },_), t2 when List.exists (fun t -> unifies t t2) tl ->
-		mk_cast to_t (mk_cast t_dynamic e)
-	| from_t, to_t when gen.gspecial_needs_cast to_t from_t ->
-		mk_cast to_t e
-	| _ ->
-		let do_default () =
-			gen.gon_unsafe_cast to_t e.etype e.epos;
-			mk_cast to_t (mk_cast t_dynamic e)
-		in
-		(* TODO: there really should be a better way to write that *)
-		try
-			if (Hashtbl.find gen.gsupported_conversions (t_path from_t)) from_t to_t then
-				mk_cast to_t e
-			else
-				do_default()
-		with
-			| Not_found ->
-				try
-					if (Hashtbl.find gen.gsupported_conversions (t_path to_t)) from_t to_t then
-						mk_cast to_t e
-					else
-						do_default()
-				with
-					| Not_found -> do_default()
-
-(* ****************************** *)
-(* cast handler *)
-(* decides if a cast should be emitted, given a from and a to type *)
-(*
-	this function is like a mini unify, without e.g. subtyping, which makes sense
-	at the backend level, since most probably Anons and TInst will have a different representation there
-*)
-let rec handle_cast gen e real_to_t real_from_t =
-	let do_unsafe_cast () = do_unsafe_cast gen real_from_t real_to_t { e with etype = real_from_t } in
-	let to_t, from_t = real_to_t, real_from_t in
-
-	let mk_cast fast t e =
-		match e.eexpr with
-			(* TThrow is always typed as Dynamic, we just need to type it accordingly *)
-			| TThrow _ -> { e with etype = t }
-			| _ -> if fast then mk_castfast t e else mk_cast t e
-	in
-
-	let e = { e with etype = real_from_t } in
-	if try fast_eq real_to_t real_from_t with Invalid_argument _ -> false then e else
-	match real_to_t, real_from_t with
-		(* string is the only type that can be implicitly converted from any other *)
-		| TInst( { cl_path = ([], "String") }, []), TInst( { cl_path = ([], "String") }, [] ) ->
-			mk_cast true to_t e
-		| TInst( { cl_path = ([], "String") }, []), _ ->
-			mk_cast false to_t e
-		| TInst( ({ cl_path = (["cs"|"java"], "NativeArray") } as c_array), [tp_to] ), TInst({ cl_path = (["cs"|"java"], "NativeArray") }, [tp_from]) when not (type_iseq gen (gen.greal_type tp_to) (gen.greal_type tp_from)) ->
-			(* see #5751 . NativeArray is special because of its ties to Array. We could potentially deal with this for all *)
-			(* TNew expressions, but it's not that simple, since we don't want to retype the whole expression list with the *)
-			(* updated type. *)
-			(match e.eexpr with
-				| TNew(c,_,el) when c == c_array ->
-					mk_cast false (TInst(c_array,[tp_to])) { e with eexpr = TNew(c, [tp_to], el); etype = TInst(c_array,[tp_to]) }
-				| _ ->
-					e
-			)
-		| TInst(cl_to, params_to), TInst(cl_from, params_from) ->
-			let ret = ref None in
-			(*
-				this is a little confusing:
-				we are here mapping classes until we have the same to and from classes, applying the type parameters in each step, so we can
-				compare the type parameters;
-
-				If a class is found - meaning that the cl_from can be converted without a cast into cl_to,
-				we still need to check their type parameters.
-			*)
-			ignore (map_cls gen (match cl_from.cl_kind,cl_to.cl_kind with KTypeParameter _, _ | _,KTypeParameter _ -> false | _ -> true) (fun _ tl ->
-				try
-					(* type found, checking type parameters *)
-					List.iter2 (type_eq gen EqStrict) tl params_to;
-					ret := Some e;
-					true
-				with | Unify_error _ ->
-					(* type parameters need casting *)
-					if gen.ghas_tparam_cast_handler then begin
-						(*
-							if we are already handling type parameter casts on other part of code (e.g. RealTypeParameters),
-							we'll just make a cast to indicate that this place needs type parameter-involved casting
-						*)
-						ret := Some (mk_cast true to_t e);
-						true
-					end else
-						(*
-							if not, we're going to check if we only need a simple cast,
-							or if we need to first cast into the dynamic version of it
-						*)
-						try
-							List.iter2 (type_eq gen EqRightDynamic) tl params_to;
-							ret := Some (mk_cast true to_t e);
-							true
-						with | Unify_error _ ->
-							ret := Some (mk_cast true to_t (mk_cast true (TInst(cl_to, List.map (fun _ -> t_dynamic) params_to)) e));
-							true
-			) cl_to cl_from params_from);
-			if is_some !ret then
-				get !ret
-			else if is_cl_related gen cl_from params_from cl_to params_to then
-				mk_cast true to_t e
-			else
-				(* potential unsafe cast *)
-				(do_unsafe_cast ())
-		| TMono _, TMono _
-		| TMono _, TDynamic _
-		| TDynamic _, TDynamic _
-		| TDynamic _, TMono _ ->
-			e
-		| TMono _, _
-		| TDynamic _, _
-		| TAnon _, _ when gen.gneeds_box real_from_t ->
-			mk_cast false to_t e
-		| TMono _, _
-		| TDynamic _, _ -> e
-		| _, TMono _
-		| _, TDynamic _ -> mk_cast false to_t e
-		| TAnon (a_to), TAnon (a_from) ->
-			if a_to == a_from then
-				e
-			else if type_iseq gen to_t from_t then (* FIXME apply unify correctly *)
-				e
-			else
-				mk_cast true to_t e
-		| _, TAnon(anon) -> (try
-			let p2 = match !(anon.a_status) with
-			| Statics c -> TInst(c,List.map (fun _ -> t_dynamic) c.cl_params)
-			| EnumStatics e -> TEnum(e, List.map (fun _ -> t_dynamic) e.e_params)
-			| AbstractStatics a -> TAbstract(a, List.map (fun _ -> t_dynamic) a.a_params)
-			| _ -> raise Not_found
-			in
-			let tclass = match get_type gen ([],"Class") with
-			| TAbstractDecl(a) -> a
-			| _ -> die "" __LOC__ in
-			handle_cast gen e real_to_t (gen.greal_type (TAbstract(tclass, [p2])))
-		with | Not_found ->
-			mk_cast false to_t e)
-		| TAbstract (a_to, _), TAbstract(a_from, _) when a_to == a_from ->
-			e
-		| TAbstract _, TInst({ cl_kind = KTypeParameter _ }, _)
-		| TInst({ cl_kind = KTypeParameter _ }, _), TAbstract _ ->
-			do_unsafe_cast()
-		| TAbstract _, _
-		| _, TAbstract _ ->
-			(try
-				unify from_t to_t;
-				mk_cast true to_t e
-			with | Unify_error _ ->
-				try
-					unify to_t from_t;
-					mk_cast true to_t e
-				with | Unify_error _ ->
-					do_unsafe_cast())
-		| TEnum(e_to, []), TEnum(e_from, []) ->
-			if e_to == e_from then
-				e
-			else
-				(* potential unsafe cast *)
-				(do_unsafe_cast ())
-		| TEnum(e_to, params_to), TEnum(e_from, params_from) when e_to.e_path = e_from.e_path ->
-			(try
-					List.iter2 (type_eq gen (if gen.gallow_tp_dynamic_conversion then EqRightDynamic else EqStrict)) params_from params_to;
-					e
-				with
-					| Unify_error _ -> do_unsafe_cast ()
-			)
-		| TEnum(en, params_to), TInst(cl, params_from)
-			| TInst(cl, params_to), TEnum(en, params_from) ->
-				(* this is here for max compatibility with EnumsToClass module *)
-			if en.e_path = cl.cl_path && Meta.has Meta.Class en.e_meta then begin
-				(try
-					List.iter2 (type_eq gen (if gen.gallow_tp_dynamic_conversion then EqRightDynamic else EqStrict)) params_from params_to;
-					e
-				with
-					| Invalid_argument _ ->
-						(*
-							this is a hack for RealTypeParams. Since there is no way at this stage to know if the class is the actual
-							EnumsToClass derived from the enum, we need to imply from possible ArgumentErrors (because of RealTypeParams interfaces),
-							that they would only happen if they were a RealTypeParams created interface
-						*)
-						e
-					| Unify_error _ -> do_unsafe_cast ()
-				)
-			end else
-				do_unsafe_cast ()
-		| TType(t_to, params_to), TType(t_from, params_from) when t_to == t_from ->
-			if gen.gspecial_needs_cast real_to_t real_from_t then
-				(try
-					List.iter2 (type_eq gen (if gen.gallow_tp_dynamic_conversion then EqRightDynamic else EqStrict)) params_from params_to;
-					e
-				with
-					| Unify_error _ -> do_unsafe_cast ()
-				)
-			else
-				e
-		| TType(t_to, _), TType(t_from,_) ->
-			if gen.gspecial_needs_cast real_to_t real_from_t then
-				mk_cast false to_t e
-			else
-				e
-		| TType _, _ when gen.gspecial_needs_cast real_to_t real_from_t ->
-			mk_cast false to_t e
-		| _, TType _ when gen.gspecial_needs_cast real_to_t real_from_t ->
-			mk_cast false to_t e
-		(*| TType(t_to, _), TType(t_from, _) ->
-			if t_to.t_path = t_from.t_path then
-				e
-			else if is_unsafe_cast gen real_to_t real_from_t then (* is_unsafe_cast will already follow both *)
-				(do_unsafe_cast ())
-			else
-				mk_cast to_t e*)
-		| TType _, _
-		| _, TType _ ->
-			if is_unsafe_cast gen real_to_t real_from_t then (* is_unsafe_cast will already follow both *)
-				(do_unsafe_cast ())
-			else
-				mk_cast false to_t e
-		| TAnon anon, _ ->
-			if PMap.is_empty anon.a_fields then
-				e
-			else
-				mk_cast true to_t e
-		| TFun(args, ret), TFun(args2, ret2) ->
-			let get_args = List.map (fun (_,_,t) -> t) in
-			(try List.iter2 (type_eq gen (EqBothDynamic)) (ret :: get_args args) (ret2 :: get_args args2); e with | Unify_error _ | Invalid_argument _ -> mk_cast true to_t e)
-		| _, _ ->
-			do_unsafe_cast ()
-
-(* end of cast handler *)
-(* ******************* *)
-
-let is_static_overload c name =
-	match c.cl_super with
-	| None -> false
-	| Some (sup,_) ->
-		let rec loop c =
-			(PMap.mem name c.cl_statics) || (match c.cl_super with
-				| None -> false
-				| Some (sup,_) -> loop sup)
-		in
-		loop sup
-
-(* this is a workaround for issue #1743, as FInstance() is returning the incorrect classfield *)
-let rec clean_t t = match follow t with
-	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
-		clean_t (Abstract.get_underlying_type a tl)
-	| t -> t
-
-let select_overload gen applied_f overloads types params =
-	let rec check_arg arglist elist =
-		match arglist, elist with
-			| [], [] -> true (* it is valid *)
-			| (_,_,t) :: [], elist when ExtType.is_rest t ->
-				(match follow t with
-				| TAbstract({ a_path = (["haxe"],"Rest") }, [t]) ->
-				List.for_all (fun (_,_,et) -> Type.type_iseq (clean_t et) (clean_t t)) elist
-				| _ -> die "" __LOC__)
-			| (_,_,t) :: arglist, (_,_,et) :: elist when Type.type_iseq (clean_t et) (clean_t t) ->
-				check_arg arglist elist
-			| _ -> false
-	in
-	match follow applied_f with
-	| TFun _ ->
-		replace_mono applied_f;
-		let args, _ = get_fun applied_f in
-		let elist = List.rev args in
-		let rec check_overload overloads =
-			match overloads with
-			| (t, cf) :: overloads ->
-					let cft = apply_params types params t in
-					let cft = monomorphs cf.cf_params cft in
-					let args, _ = get_fun cft in
-					if check_arg (List.rev args) elist then
-						cf,t,false
-					else if overloads = [] then
-						cf,t,true (* no compatible overload was found *)
-					else
-						check_overload overloads
-			| [] -> die "" __LOC__
-		in
-		check_overload overloads
-	| _ -> match overloads with  (* issue #1742 *)
-	| (t,cf) :: [] -> cf,t,true
-	| (t,cf) :: _ -> cf,t,false
-	| _ -> die "" __LOC__
-
-let rec cur_ctor c tl =
-	match c.cl_constructor with
-	| Some ctor ->
-		ctor, c, tl
-	| None ->
-		match c.cl_super with
-		| None ->
-			raise Not_found
-		| Some (sup,stl) ->
-			cur_ctor sup (List.map (apply_params c.cl_params tl) stl)
-
-let choose_ctor gen cl tparams etl maybe_empty_t p =
-	let ctor, sup, stl = cur_ctor cl tparams in
-	(* get returned stl, with Dynamic as t_empty *)
-	let rec get_changed_stl c tl =
-		if c == sup then
-			tl
-		else match c.cl_super with
-		| None -> stl
-		| Some(sup,stl) -> get_changed_stl sup (List.map (apply_params c.cl_params tl) stl)
-	in
-	let ret_tparams = List.map (fun t -> match follow t with
-		| TDynamic _ | TMono _ -> t_empty
-		| _ -> t) tparams
-	in
-	let ret_stl = get_changed_stl cl ret_tparams in
-	let ctors = ctor :: ctor.cf_overloads in
-	List.iter replace_mono etl;
-	(* first filter out or select outright maybe_empty *)
-	let ctors, is_overload = match etl, maybe_empty_t with
-		| [t], Some empty_t ->
-			let count = ref 0 in
-			let is_empty_call = Type.type_iseq t empty_t in
-			let ret = List.filter (fun cf -> match follow cf.cf_type with
-				| TFun([_,_,t],_) ->
-					replace_mono t; incr count; is_empty_call = (Type.type_iseq t empty_t)
-				| _ -> false) ctors
-			in
-			ret, !count > 1
-		| _ ->
-			let len = List.length etl in
-			let ret = List.filter (fun cf -> List.length (fst (get_fun cf.cf_type)) <= len) ctors in
-			ret, (match ret with | _ :: [] -> false | _ -> true)
-	in
-	let rec check_arg arglist elist =
-		match arglist, elist with
-		| [], [] -> true
-		| [(_,_,t)], elist when ExtType.is_rest (follow t) ->
-			(match follow t with
-			| TAbstract ({ a_path = ["haxe"],"Rest" } as a, [t1]) ->
-				let is_rest_array arg_t =
-					let boxed = TAbstract (a, [get_boxed gen t1]) in
-					Type.fast_eq (Abstract.follow_with_abstracts boxed) (Abstract.follow_with_abstracts arg_t)
-				in
-				(match elist with
-				| [arg_t] when is_rest_array arg_t -> true
-				| _ ->
-						let t1 = run_follow gen t1 in
-						(try
-							List.iter (fun et -> unify et t1) elist;
-							true
-						with Unify_error _ ->
-							false
-						)
-				)
-			| _ -> die "" __LOC__
-			)
-		| (_,_,t) :: arglist, et :: elist ->
-			(try
-				let t = run_follow gen t in
-				unify et t;
-				check_arg arglist elist
-			with Unify_error el ->
-				false
-			)
-		| _ ->
-			false
-	in
-	let rec check_cf cf =
-		let t = apply_params sup.cl_params stl cf.cf_type in
-		replace_mono t;
-		let args, _ = get_fun t in
-		check_arg args etl
-	in
-	match is_overload, ctors with
-		| false, [c] ->
-			false, c, sup, ret_stl
-		| _ ->
-			is_overload, List.find check_cf ctors, sup, ret_stl
-
-let change_rest tfun elist =
-	let expects_rest_args = ref false in
-	let rec loop acc arglist elist = match arglist, elist with
-		| (_,_,t) as arg :: [], elist when ExtType.is_rest t ->
-			(match elist with
-			| [{ eexpr = TUnop (Spread,Prefix,e) }] ->
-				List.rev (arg :: acc)
-			| _ ->
-				(match follow t with
-				| TAbstract({ a_path = (["haxe"],"Rest") },[t1]) ->
-					let is_rest_array e =
-						Type.fast_eq (Abstract.follow_with_abstracts t) (Abstract.follow_with_abstracts e.etype)
-					in
-					(match elist with
-					| [e] when is_rest_array e ->
-						List.rev (("rest",false,t) :: acc)
-					| _ ->
-						expects_rest_args := true;
-						List.rev (List.map (fun _ -> "rest",false,t1) elist @ acc)
-					)
-				| _ -> die "" __LOC__)
-			)
-		| (n,o,t) :: arglist, _ :: elist ->
-			loop ((n,o,t) :: acc) arglist elist
-		| _, _ ->
-			List.rev acc
-	in
-	let args,ret = get_fun tfun in
-	let args_types = loop [] args elist in
-	!expects_rest_args,TFun(args_types, ret)
-
-let fastcast_if_needed gen expr real_to_t real_from_t =
-	if Common.defined gen.gcon Define.FastCast then begin
-		if type_iseq gen real_to_t real_from_t then
-			{ expr with etype = real_to_t }
-		else
-			mk_castfast real_to_t { expr with etype=real_from_t }
-	end else
-		handle_cast gen expr real_to_t real_from_t
-
-(*
-	Type parameter handling
-	It will detect if/what type parameters were used, and call the cast handler
-	It will handle both TCall(TField) and TCall by receiving a texpr option field: e
-	Also it will transform the type parameters with greal_type_param and make
-
-	handle_impossible_tparam - should cases where the type parameter is impossible to be determined from the called parameters be Dynamic?
-	e.g. static function test<T>():T {}
-*)
-
-(* match e.eexpr with | TCall( ({ eexpr = TField(ef, f) }) as e1, elist ) -> *)
-let handle_type_parameter gen e e1 ef ~clean_ef ~overloads_cast_to_base f elist calls_parameters_explicitly =
-	(* the ONLY way to know if this call has parameters is to analyze the calling field. *)
-	(* To make matters a little worse, on both C# and Java only in some special cases that type parameters will be used *)
-	(* Namely, when using reflection type parameters are useless, of course. This also includes anonymous types *)
-	(* this will have to be handled by gparam_func_call *)
-
-	let return_var efield =
-		match e with
-			| None ->
-				efield
-			| Some ecall ->
-				match follow efield.etype with
-					| TFun(_,ret) ->
-						(* closures will be handled by the closure handler. So we will just hint what's the expected type *)
-						(* FIXME: should closures have also its arguments cast correctly? In the current implementation I think not. TO_REVIEW *)
-						handle_cast gen { ecall with eexpr = TCall(efield, elist) } (gen.greal_type ecall.etype) ret
-					| _ ->
-						{ ecall with eexpr = TCall(efield, elist) }
-	in
-
-	(* this function will receive the original function argument, the applied function argument and the original function parameters. *)
-	(* from this info, it will infer the applied tparams for the function *)
-	let infer_params pos (original_args:((string * bool * t) list * t)) (applied_args:((string * bool * t) list * t)) (params:typed_type_param list) calls_parameters_explicitly : tparams =
-		match params with
-		| [] -> []
-		| _ ->
-			let args_list args = (if not calls_parameters_explicitly then t_dynamic else snd args) :: (List.map (fun (n,o,t) -> t) (fst args)) in
-
-			let monos = List.map (fun _ -> mk_mono()) params in
-			let original = args_list (get_fun (apply_params params monos (TFun(fst original_args,snd original_args)))) in
-			let applied = args_list applied_args in
-
-			(try
-				List.iter2 (fun a o ->
-					unify a o
-					(* type_eq EqStrict a o *)
-				) applied original
-				(* unify applied original *)
-			with
-				| Unify_error el ->
-						(match el with
-						(*
-							Don't emit a warning for abstracts if underlying type is the same as the second type.
-							This situation is caused by `Normalize.filter_param` not "unpacking" abstracts.
-						*)
-						| [Cannot_unify (TAbstract(a,params), b)]
-						| [Cannot_unify (b, TAbstract(a,params))] ->
-							let a = apply_params a.a_params params a.a_this in
-							if not (shallow_eq a b) then
-								gen.gwarning WGenerator ("This expression may be invalid") pos
-						| _ ->
-							gen.gwarning WGenerator ("This expression may be invalid") pos
-						)
-				| Invalid_argument _ ->
-						gen.gwarning WGenerator ("This expression may be invalid") pos
-			);
-
-			List.map (fun t ->
-				match follow_without_null t with
-					| TMono _ ->	t_empty
-					| t -> t
-			) monos
-	in
-
-	let real_type = gen.greal_type ef.etype in
-	(* this part was rewritten at roughly r6477 in order to correctly support overloads *)
-	(match field_access_esp gen real_type (f) with
-	| FClassField (cl, params, _, cf, is_static, actual_t, declared_t) when e <> None && (cf.cf_kind = Method MethNormal || cf.cf_kind = Method MethInline) ->
-			(* C# target changes params with a real_type function *)
-			let params = match follow clean_ef.etype with
-				| TInst(_,params) -> params
-				| _ -> params
-			in
-			let local_mk_cast t expr =
-				(* handle_cast gen expr t expr.etype *)
-				if is_exactly_basic gen t expr.etype then
-					expr
-				else
-					mk_castfast t expr
-			in
-
-			let ecall = get e in
-			let ef = ref ef in
-			let is_overload = cf.cf_overloads <> [] || has_class_field_flag cf CfOverload || (is_static && is_static_overload cl (field_name f)) in
-			let cf, actual_t, error = match is_overload with
-				| false ->
-						(* since actual_t from FClassField already applies greal_type, we're using the get_overloads helper to get this info *)
-						let t = if cf.cf_params = [] then (* this if statement must be eliminated - it's a workaround for #3516 + infer params. *)
-							actual_t
-						else
-							declared_t
-						in
-						cf,t,false
-				| true ->
-				let (cf, actual_t, error), is_static = match f with
-					| FInstance(c,_,cf) | FClosure(Some (c,_),cf) ->
-						(* get from overloads *)
-						(* FIXME: this is a workaround for issue #1743 . Uncomment this code after it was solved *)
-						(* let t, cf = List.find (fun (t,cf2) -> cf == cf2) (Overloads.get_overloads cl (field_name f)) in *)
-						(* cf, t, false *)
-						select_overload gen e1.etype (Overloads.collect_overloads (fun t -> t) cl (field_name f)) cl.cl_params params, false
-					| FStatic(c,f) ->
-						(* workaround for issue #1743 *)
-						(* f,f.cf_type, false *)
-						select_overload gen e1.etype ((f.cf_type,f) :: List.map (fun f -> f.cf_type,f) f.cf_overloads) [] [], true
-					| _ ->
-						gen.gwarning WGenerator "Overloaded classfield typed as anonymous" ecall.epos;
-						(cf, actual_t, true), true
-				in
-
-				if not (is_static || error) then match find_first_declared_field gen cl ~exact_field:{ cf with cf_type = actual_t } cf.cf_name with
-				| Some(cf_orig,actual_t,_,_,declared_cl,tl,tlch) ->
-					let rec is_super e = match e.eexpr with
-						| TConst TSuper -> true
-						| TParenthesis p | TMeta(_,p) -> is_super p
-						| _ -> false
-					in
-					if declared_cl != cl && overloads_cast_to_base && not (is_super !ef) then begin
-						let pos = (!ef).epos in
-						ef := {
-							eexpr = TCall(
-								{ eexpr = TIdent "__as__"; etype = t_dynamic; epos = pos },
-								[!ef]);
-							etype = TInst(declared_cl,List.map (apply_params cl.cl_params params) tl);
-							epos = pos
-						}
-					end;
-					{ cf_orig with cf_name = cf.cf_name },actual_t,false
-				| None ->
-					gen.gwarning WGenerator "Cannot find matching overload" ecall.epos;
-					cf, actual_t, true
-				else
-					cf,actual_t,error
-			in
-
-			(* take off Rest param *)
-			let _,actual_t = change_rest actual_t elist in
-			(* set the real (selected) class field *)
-			let f = match f with
-				| FInstance(c,tl,_) -> FInstance(c,tl,cf)
-				| FClosure(c,_) -> FClosure(c,cf)
-				| FStatic(c,_) -> FStatic(c,cf)
-				| f -> f
-			in
-			let error = error || (match follow actual_t with | TFun _ -> false | _ -> true) in
-			if error then (* if error, ignore arguments *)
-				if ExtType.is_void ecall.etype then
-					{ ecall with eexpr = TCall({ e1 with eexpr = TField(!ef, f) }, elist ) }
-				else
-					local_mk_cast ecall.etype { ecall with eexpr = TCall({ e1 with eexpr = TField(!ef, f) }, elist ) }
-			else begin
-				(* infer arguments *)
-				(* let called_t = TFun(List.map (fun e -> "arg",false,e.etype) elist, ecall.etype) in *)
-				let called_t = match follow e1.etype with | TFun _ -> e1.etype | _ -> TFun(List.map (fun e -> "arg",false,e.etype) elist, ecall.etype)	in (* workaround for issue #1742 *)
-				let expects_rest_args,called_t = change_rest called_t elist in
-				let original = (get_fun (apply_params cl.cl_params params actual_t)) in
-				let applied = (get_fun called_t) in
-				let fparams = infer_params ecall.epos original applied cf.cf_params calls_parameters_explicitly in
-				(* get what the backend actually sees *)
-				(* actual field's function *)
-				let actual_t = get_real_fun gen actual_t in
-				let real_params = gen.greal_type_param (TClassDecl cl) params in
-				let function_t = apply_params cl.cl_params real_params actual_t in
-				let real_fparams = if calls_parameters_explicitly then
-					gen.greal_type_param (TClassDecl cl) fparams
-				else
-					gen.greal_type_param (TClassDecl cl) (infer_params ecall.epos (get_fun function_t) (get_fun (get_real_fun gen called_t)) cf.cf_params calls_parameters_explicitly) in
-				let function_t = get_real_fun gen (apply_params cf.cf_params real_fparams function_t) in
-				let args_ft, ret_ft = get_fun function_t in
-				(* applied function *)
-				let applied = elist in
-				(* check types list *)
-				let new_ecall, elist = try
-					let fn = fun funct applied  ->
-						match is_overload || real_fparams <> [], applied.eexpr with
-						| true, TConst TNull ->
-							mk_castfast (gen.greal_type funct) applied
-						| true, _ -> (* when not (type_iseq gen (gen.greal_type applied.etype) funct) -> *)
-							let ret = handle_cast gen applied (funct) (gen.greal_type applied.etype) in
-							(match ret.eexpr with
-							| TCast _ -> ret
-							| _ -> local_mk_cast (funct) ret)
-						| _ ->
-							handle_cast gen applied (funct) (gen.greal_type applied.etype)
-					in
-					let rec loop args_ft applied =
-						match args_ft, applied with
-						| [], [] -> []
-						| [(_,_,funct)], _ when expects_rest_args ->
-							(match funct, applied with
-							| _,[{ eexpr = TUnop(Spread,Prefix,a) }]
-							| _,[{ eexpr = TParenthesis({ eexpr = TUnop(Spread,Prefix,a) }) }] ->
-								[fn funct a]
-							| TInst({ cl_path = (_,"NativeArray") },[funct]),_ ->
-								List.map (fn funct) applied
-							| _, a :: applied ->
-								(fn funct a) :: loop args_ft applied
-							| _, [] ->
-								[]
-							)
-						| (_,_,funct)::args_ft, a::applied ->
-							(fn funct a) :: loop args_ft applied
-						| _ -> raise (Invalid_argument "Args length mismatch")
-					in
-					let elist = loop args_ft applied in
-					{ ecall with
-						eexpr = TCall(
-							{ e1 with eexpr = TField(!ef, f) },
-							elist);
-					}, elist
-				with Invalid_argument _ ->
-					gen.gwarning WGenerator ("This expression may be invalid" ) ecall.epos;
-					{ ecall with eexpr = TCall({ e1 with eexpr = TField(!ef, f) }, elist) }, elist
-				in
-				let new_ecall = if fparams <> [] then gen.gparam_func_call new_ecall { e1 with eexpr = TField(!ef, f) } fparams elist else new_ecall in
-				let ret = handle_cast gen new_ecall (gen.greal_type ecall.etype) (gen.greal_type ret_ft) in
-				(match gen.gcon.platform, cf.cf_params, ret.eexpr with
-					| _, _, TCast _ -> ret
-					| Java, _ :: _, _ ->
-						(* this is a workaround for a javac openjdk issue with unused type parameters and return type inference *)
-						(* see more at issue #3123 *)
-						mk_cast (gen.greal_type ret_ft) new_ecall
-					| _ -> ret)
-			end
-	| FClassField (cl,params,_,{ cf_kind = (Method MethDynamic | Var _) },_,actual_t,_) ->
-		(* if it's a var, we will just try to apply the class parameters that have been changed with greal_type_param *)
-		let t = apply_params cl.cl_params (gen.greal_type_param (TClassDecl cl) params) (gen.greal_type actual_t) in
-		return_var (handle_cast gen { e1 with eexpr = TField(ef, f) } (gen.greal_type e1.etype) (gen.greal_type t))
-	| FClassField (cl,params,_,cf,_,actual_t,_) ->
-		return_var (handle_cast gen { e1 with eexpr = TField({ ef with etype = t_dynamic }, f) } e1.etype t_dynamic) (* force dynamic and cast back to needed type *)
-	| FEnumField (en, efield, true) ->
-		let ecall = match e with | None -> trace (field_name f); trace efield.ef_name; gen.gcon.error "This field should be called immediately" ef.epos; die "" __LOC__ | Some ecall -> ecall in
-		(match en.e_params with
-			(*
-			| [] ->
-				let args, ret = get_fun (efield.ef_type) in
-				let ef = { ef with eexpr = TTypeExpr( TEnumDecl en ); etype = TEnum(en, []) } in
-				handle_cast gen { ecall with eexpr = TCall({ e1 with eexpr = TField(ef, FEnum(en, efield)) }, List.map2 (fun param (_,_,t) -> handle_cast gen param (gen.greal_type t) (gen.greal_type param.etype)) elist args) } (gen.greal_type ecall.etype) (gen.greal_type ret)
-		*)
-			| _ ->
-				let pt = match e with | None -> real_type | Some _ -> snd (get_fun e1.etype) in
-				let _params = match follow pt with | TEnum(_, p) -> p | _ -> gen.gwarning WGenerator (debug_expr e1) e1.epos; die "" __LOC__ in
-				let args, ret = get_fun efield.ef_type in
-				let actual_t = TFun(List.map (fun (n,o,t) -> (n,o,gen.greal_type t)) args, gen.greal_type ret) in
-				(*
-					because of differences on how <Dynamic> is handled on the platforms, this is a hack to be able to
-					correctly use class field type parameters with RealTypeParams
-				*)
-				let cf_params = List.map (fun t -> match follow t with | TDynamic _ -> t_empty | _ -> t) _params in
-				let t = apply_params en.e_params (gen.greal_type_param (TEnumDecl en) cf_params) actual_t in
-				let t = apply_params efield.ef_params (List.map (fun _ -> t_dynamic) efield.ef_params) t in
-
-				let args, ret = get_fun t in
-
-				let elist = List.map2 (fun param (_,_,t) -> handle_cast gen (param) (gen.greal_type t) (gen.greal_type param.etype)) elist args in
-				let e1 = { e1 with eexpr = TField({ ef with eexpr = TTypeExpr( TEnumDecl en ); etype = TEnum(en, _params) }, FEnum(en, efield) ) } in
-				let new_ecall = gen.gparam_func_call ecall e1 _params elist in
-
-				handle_cast gen new_ecall (gen.greal_type ecall.etype) (gen.greal_type ret)
-		)
-	| FEnumField _ when is_some e -> die "" __LOC__
-	| FEnumField (en,efield,_) ->
-			return_var { e1 with eexpr = TField({ ef with eexpr = TTypeExpr( TEnumDecl en ); },FEnum(en,efield)) }
-	(* no target by date will uses this.so this code may not be correct at all *)
-	| FAnonField cf ->
-		let t = gen.greal_type cf.cf_type in
-		return_var (handle_cast gen { e1 with eexpr = TField(ef, f) } (gen.greal_type e1.etype) t)
-	| FNotFound
-	| FDynamicField _ ->
-		if is_some e then
-			return_var { e1 with eexpr = TField(ef, f) }
-		else
-			return_var (handle_cast gen { e1 with eexpr = TField({ ef with etype = t_dynamic }, f) } e1.etype t_dynamic) (* force dynamic and cast back to needed type *)
-	)
-
-(* end of type parameter handling *)
-(* ****************************** *)
-
-(** overloads_cast_to_base argument will cast overloaded function types to the class that declared it. **)
-(**			This is necessary for C#, and if true, will require the target to implement __as__, as a `quicker` form of casting **)
-let configure gen ?(overloads_cast_to_base = false) maybe_empty_t calls_parameters_explicitly =
-	let handle e t1 t2 = handle_cast gen e (gen.greal_type t1) (gen.greal_type t2) in
-
-	let in_value = ref false in
-
-	let rec clean_cast e = match e.eexpr with
-		| TCast(e,_) -> clean_cast e
-		| TParenthesis(e) | TMeta(_,e) -> clean_cast e
-		| _ -> e
-	in
-
-	let get_abstract_impl t = match t with
-		| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-			Abstract.get_underlying_type a pl
-		| t -> t
-	in
-
-	let rec is_abstract_to_struct t = match t with
-		| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-			is_abstract_to_struct (Abstract.get_underlying_type a pl)
-		| TInst(c,_) when Meta.has Meta.Struct c.cl_meta ->
-			true
-		| _ -> false
-	in
-
-	let binop_type fast_cast op main_expr e1 e2 =
-		let name = platform_name gen.gcon.platform in
-		let basic = gen.gcon.basic in
-		(* If either operand is of type decimal, the other operand is converted to type decimal, or a compile-time error occurs if the other operand is of type float or double.
-			* Otherwise, if either operand is of type double, the other operand is converted to type double.
-			* Otherwise, if either operand is of type float, the other operand is converted to type float.
-			* Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a compile-time error occurs if the other operand is of type sbyte, short, int, or long.
-			* Otherwise, if either operand is of type long, the other operand is converted to type long.
-			* Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
-			* Otherwise, if either operand is of type uint, the other operand is converted to type uint.
-			* Otherwise, both operands are converted to type int.
-			*  *)
-		let t1, t2 = follow (run_follow gen e1.etype), follow (run_follow gen e2.etype) in
-		let result =
-			match t1, t2 with
-			| TAbstract(a1,[]), TAbstract(a2,[]) when fast_cast && a1 == a2 ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype }
-			| TInst(i1,[]), TInst(i2,[]) when fast_cast && i1 == i2 ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype }
-			| TInst({ cl_path = ([],"String") },[]), _ when fast_cast && op = OpAdd ->
-				{ main_expr with eexpr = TBinop(op, e1, mk_cast basic.tstring e2); etype = basic.tstring }
-			| _, TInst({ cl_path = ([],"String") },[]) when fast_cast && op = OpAdd ->
-				{ main_expr with eexpr = TBinop(op, mk_cast basic.tstring e1, e2); etype = basic.tstring }
-			| TAbstract({ a_path = ([], "Float") }, []), _ when fast_cast ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype }
-			| _, TAbstract({ a_path = ([], "Float") }, []) when fast_cast ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype }
-			| TAbstract({ a_path = ([], "Single") }, []), _ when fast_cast ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype }
-			| _, TAbstract({ a_path = ([], "Single") }, []) when fast_cast ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype }
-			| TAbstract({ a_path = ([pf], "UInt64") }, []), _ when fast_cast && pf = name ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype }
-			| _, TAbstract({ a_path = ([pf], "UInt64") }, []) when fast_cast && pf = name ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype }
-			| TAbstract({ a_path = ([pf], "Int64") }, []), _ when fast_cast && pf = name ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype }
-			| _, TAbstract({ a_path = ([pf], "Int64") }, []) when fast_cast && pf = name ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype }
-			| TAbstract({ a_path = ([], "UInt") }, []), tother when like_int tother ->
-				let ti64 = mt_to_t_dyn ( get_type gen ([name], "Int64") ) in
-				let ret = { main_expr with eexpr = TBinop(op, e1, e2); etype = ti64 } in
-				if op <> OpDiv then
-					mk_cast t1 ret
-				else
-					ret
-			| tother, TAbstract({ a_path = ([], "UInt") }, []) when like_int tother ->
-				let ti64 = mt_to_t_dyn ( get_type gen ([name], "Int64") ) in
-				let ret = { main_expr with eexpr = TBinop(op, e1, e2); etype = ti64 } in
-				if op <> OpDiv then
-					mk_cast t2 ret
-				else
-					ret
-			| TAbstract({ a_path = ([], "UInt") }, []), _ ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e1.etype }
-			| _, TAbstract({ a_path = ([], "UInt") }, []) ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = e2.etype }
-			| TAbstract(a1,[]), TAbstract(a2,[]) when fast_cast ->
-				{ main_expr with eexpr = TBinop(op, e1, e2); etype = basic.tint }
-			| _ ->
-				{ main_expr with eexpr = TBinop(op, e1, e2) }
-		in
-		(* maintain nullability *)
-		match follow_without_null main_expr.etype, follow_without_null result.etype with
-		| TAbstract ({ a_path = ([],"Null") },_), TAbstract ({ a_path = ([],"Null") },_) ->
-			result
-		| TAbstract ({ a_path = ([],"Null") } as null,_), _ ->
-			{ result with etype = TAbstract(null, [result.etype]) }
-		| _, TAbstract ({ a_path = ([],"Null") },[t]) ->
-			{ result with etype = t }
-		| _ -> result
-	in
-	let binop_type = binop_type (Common.defined gen.gcon Define.FastCast) in
-
-	let rec run ?(just_type = false) e =
-		let handle = if not just_type then handle else fun e t1 t2 -> { e with etype = gen.greal_type t2 } in
-		let was_in_value = !in_value in
-		in_value := true;
-		match e.eexpr with
-			| TConst ( TInt _ | TFloat _ | TBool _ as const ) ->
-				(* take off any Null<> that it may have *)
-				let t = follow (run_follow gen e.etype) in
-				(* do not allow constants typed as Single - need to cast them *)
-				let real_t = match const with
-					| TInt _ -> gen.gcon.basic.tint
-					| TFloat _ -> gen.gcon.basic.tfloat
-					| TBool _ -> gen.gcon.basic.tbool
-					| _ -> die "" __LOC__
-				in
-				handle e t real_t
-			| TCast( { eexpr = TConst TNull }, _ ) ->
-				{ e with eexpr = TConst TNull }
-			| TCast( { eexpr = TCall( { eexpr = TIdent "__delegate__" } as local, [del] ) } as e2, _) ->
-				{ e with eexpr = TCast({ e2 with eexpr = TCall(local, [Type.map_expr run del]) }, None) }
-
-			| TBinop (OpAssignOp (Ast.OpShl | Ast.OpShr | Ast.OpUShr as op), e1, e2 ) ->
-				let e1 = run ~just_type:true e1 in
-				let e2 = handle (run e2) (gen.gcon.basic.tint) e2.etype in
-				let rett = binop_type op e e1 e2 in
-				{ e with eexpr = TBinop(OpAssignOp op, e1, e2); etype = rett.etype }
-			| TBinop ( (Ast.OpAssign | Ast.OpAssignOp _ as op), e1, e2 ) ->
-				let e1 = run ~just_type:true e1 in
-				let e2 = handle (run e2) e1.etype e2.etype in
-				{ e with eexpr = TBinop(op, clean_cast e1, e2) }
-			| TBinop ( (Ast.OpShl | Ast.OpShr | Ast.OpUShr as op), e1, e2 ) ->
-				let e1 = run e1 in
-				let e2 = handle (run e2) (gen.gcon.basic.tint) e2.etype in
-				let rett = binop_type op e e1 e2 in
-				{ e with eexpr = TBinop(op, e1, e2); etype = rett.etype }
-			| TBinop( (OpAdd | OpMult | OpDiv | OpSub | OpAnd | OpOr | OpXor | OpMod) as op, e1, e2 ) ->
-				binop_type op e (run e1) (run e2)
-			| TBinop( (OpEq | OpNotEq | OpGt | OpGte | OpLt | OpLte | OpBoolAnd | OpBoolOr) as op, e1, e2 ) ->
-				handle { e with eexpr = TBinop(op, run e1, run e2) } e.etype gen.gcon.basic.tbool
-			| TField(ef, f) ->
-				handle_type_parameter gen None e (run ef) ~clean_ef:ef ~overloads_cast_to_base:overloads_cast_to_base f [] calls_parameters_explicitly
-			| TArrayDecl el ->
-				let et = e.etype in
-				let base_type = match follow et with
-					| TInst({ cl_path = ([], "Array") } as cl, bt) -> gen.greal_type_param (TClassDecl cl) bt
-					| _ ->
-						gen.gwarning WGenerator (debug_type et) e.epos;
-						(match gen.gcurrent_class with
-							| Some cl -> print_endline (s_type_path cl.cl_path)
-							| _ -> ());
-						die "" __LOC__
-				in
-				let base_type = List.hd base_type in
-				{ e with eexpr = TArrayDecl( List.map (fun e -> handle (run e) base_type e.etype) el ); etype = et }
-			| TCall ({ eexpr = TIdent "__array__" } as arr_local, el) ->
-				let et = e.etype in
-				let base_type = match follow et with
-					| TInst(cl, bt) -> gen.greal_type_param (TClassDecl cl) bt
-					| _ -> die "" __LOC__
-				in
-				let base_type = List.hd base_type in
-				{ e with eexpr = TCall(arr_local, List.map (fun e -> handle (run e) base_type e.etype) el ); etype = et }
-			| TCall( ({ eexpr = TIdent s } as local), params ) when String.get s 0 = '_' && String.get s 1 = '_' && Hashtbl.mem gen.gspecial_vars s ->
-				{ e with eexpr = TCall(local, List.map (fun e -> (match e.eexpr with TBlock _ -> in_value := false | _ -> ()); run e) params) }
-			| TCall( ({ eexpr = TField(ef, f) }) as e1, elist ) ->
-				handle_type_parameter gen (Some e) (e1) (run ef) ~clean_ef:ef ~overloads_cast_to_base:overloads_cast_to_base f (List.map run elist) calls_parameters_explicitly
-
-			| TCall( { eexpr = TConst TSuper } as ef, eparams ) ->
-				let cl, tparams = match follow ef.etype with
-				| TInst(cl,p) ->
-					cl,p
-				| _ -> die "" __LOC__ in
-				(try
-					let is_overload, cf, sup, stl = choose_ctor gen cl tparams (List.map (fun e -> e.etype) eparams) maybe_empty_t e.epos in
-					let handle e t1 t2 =
-						if is_overload then
-							let ret = handle e t1 t2 in
-							match ret.eexpr with
-							| TCast _ -> ret
-							| _ -> mk_cast (gen.greal_type t1) e
-						else
-							handle e t1 t2
-					in
-					let stl = gen.greal_type_param (TClassDecl sup) stl in
-					let args,rt = get_fun (apply_params sup.cl_params stl cf.cf_type) in
-					let eparams = List.map2 (fun e (_,_,t) ->
-						handle (run e) t e.etype
-					) (wrap_rest_args gen (TFun (args,rt)) eparams e.epos) args in
-					{ e with eexpr = TCall(ef, eparams) }
-				with | Not_found ->
-					gen.gwarning WGenerator "No overload found for this constructor call" e.epos;
-					{ e with eexpr = TCall(ef, List.map run eparams) })
-			| TCall (ef, eparams) ->
-				(match ef.etype with
-					| TFun(p, ret) ->
-						handle ({ e with eexpr = TCall(run ef, List.map2 (fun param (_,_,t) -> handle (run param) t param.etype) eparams p) }) e.etype ret
-					| _ -> Type.map_expr run e
-				)
-			| TNew ({ cl_kind = KTypeParameter _ }, _, _) ->
-				Type.map_expr run e
-			| TNew (cl, tparams, eparams) -> (try
-				let is_overload, cf, sup, stl = choose_ctor gen cl tparams (List.map (fun e -> e.etype) eparams) maybe_empty_t e.epos in
-				let handle e t1 t2 =
-					if is_overload then
-						let ret = handle e t1 t2 in
-						match ret.eexpr with
-						| TCast _ -> ret
-						| _ -> mk_cast (gen.greal_type t1) e
-					else
-						handle e t1 t2
-				in
-				let stl = gen.greal_type_param (TClassDecl sup) stl in
-				let args,rt = get_fun (apply_params sup.cl_params stl cf.cf_type) in
-				let eparams = List.map2 (fun e (_,_,t) ->
-					handle (run e) t e.etype
-				) (wrap_rest_args gen (TFun (args,rt)) eparams e.epos) args in
-				{ e with eexpr = TNew(cl, tparams, eparams) }
-			with | Not_found ->
-				gen.gwarning WGenerator "No overload found for this constructor call" e.epos;
-				{ e with eexpr = TNew(cl, tparams, List.map run eparams) })
-			| TUnop((Increment | Decrement) as op, flag, ({ eexpr = TArray (arr, idx) } as e2))
-				when (match follow arr.etype with TInst({ cl_path = ["cs"],"NativeArray" },_) -> true | _ -> false) ->
-				{ e with eexpr = TUnop(op, flag, { e2 with eexpr = TArray(run arr, idx) })}
-			| TArray(arr, idx) ->
-				let arr_etype = match follow arr.etype with
-					| (TInst _ as t) -> t
-					| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-						follow (Abstract.get_underlying_type a pl)
-					| t -> t
-				in
-				let idx = run idx in
-				let idx = match gen.greal_type idx.etype with
-					| TAbstract({ a_path = [],"Int" },_) -> idx
-					| _ -> match handle idx gen.gcon.basic.tint (gen.greal_type idx.etype) with
-						| ({ eexpr = TCast _ } as idx) -> idx
-						| idx -> mk_cast gen.gcon.basic.tint idx
-				in
-				let e = { e with eexpr = TArray(run arr, idx) } in
-				(* get underlying class (if it's a class *)
-				(match arr_etype with
-					| TInst({ cl_path = ["cs"],"NativeArray" }, _) when
-							(match Abstract.follow_with_abstracts e.etype with TInst _ | TEnum _ -> true | _ -> false)
-							|| Common.defined gen.gcon Define.EraseGenerics
-						->
-						mk_cast e.etype e
-					| TInst(cl, params) ->
-						(* see if it implements ArrayAccess *)
-						(match cl.cl_array_access with
-							| None -> e
-							| Some t ->
-								(* if it does, apply current parameters (and change them) *)
-								(* let real_t = apply_params_internal (List.map (gen.greal_type_param (TClassDecl cl))) cl params t in *)
-								let param = apply_params cl.cl_params (gen.greal_type_param (TClassDecl cl) params) t in
-								let real_t = apply_params cl.cl_params params param in
-								(* see if it needs a cast *)
-
-								fastcast_if_needed gen e (gen.greal_type e.etype) (gen.greal_type real_t)
-								(* handle (e) (gen.greal_type e.etype) (gen.greal_type real_t) *)
-						)
-					| _ -> Type.map_expr run e)
-			| TVar (v, eopt) ->
-				{ e with eexpr = TVar (v, match eopt with
-						| None -> eopt
-						| Some e -> Some( handle (run e) v.v_type e.etype ))
-				}
-			(* FIXME deal with in_value when using other statements that may not have a TBlock wrapped on them *)
-			| TIf (econd, ethen, Some(eelse)) when was_in_value ->
-				{ e with eexpr = TIf (handle (run econd) gen.gcon.basic.tbool econd.etype, handle (run ethen) e.etype ethen.etype, Some( handle (run eelse) e.etype eelse.etype ) ) }
-			| TIf (econd, ethen, eelse) ->
-				{ e with eexpr = TIf (handle (run econd) gen.gcon.basic.tbool econd.etype, (in_value := false; run (mk_block ethen)), Option.map (fun e -> in_value := false; run (mk_block e)) eelse) }
-			| TWhile (econd, e1, flag) ->
-				{ e with eexpr = TWhile (handle (run econd) gen.gcon.basic.tbool econd.etype, (in_value := false; run (mk_block e1)), flag) }
-			| TSwitch (cond, el_e_l, edef) ->
-				{ e with eexpr = TSwitch(run cond, List.map (fun (el,e) -> (List.map run el, (in_value := false; run (mk_block e)))) el_e_l, Option.map (fun e -> in_value := false; run (mk_block e)) edef) }
-			| TFor (v,cond,e1) ->
-				{ e with eexpr = TFor(v, run cond, (in_value := false; run (mk_block e1))) }
-			| TTry (e, ve_l) ->
-				{ e with eexpr = TTry((in_value := false; run (mk_block e)), List.map (fun (v,e) -> in_value := false; (v, run (mk_block e))) ve_l) }
-			| TBlock el ->
-				let i = ref 0 in
-				let len = List.length el in
-				{ e with eexpr = TBlock ( List.map (fun e ->
-					incr i;
-					if !i <> len || not was_in_value then
-						in_value := false;
-					run e
-				) el ) }
-			| TCast (expr, md) when ExtType.is_void (follow e.etype) ->
-				run expr
-			| TCast (expr, md) ->
-				let rec get_null e =
-					match e.eexpr with
-					| TConst TNull -> Some e
-					| TParenthesis e | TMeta(_,e) -> get_null e
-					| _ -> None
-				in
-
-				(match get_null expr with
-				| Some enull ->
-						if gen.gcon.platform = Cs then
-							{ enull with etype = gen.greal_type e.etype }
-						else
-							mk_cast (gen.greal_type e.etype) enull
-				| _ when is_abstract_to_struct expr.etype && type_iseq gen e.etype (get_abstract_impl expr.etype) ->
-					run { expr with etype = expr.etype }
-				| _ when is_exactly_basic gen expr.etype e.etype ->
-					run { expr with etype = expr.etype }
-				| _ ->
-					match gen.greal_type e.etype, gen.greal_type expr.etype with
-						| (TInst(c,tl) as tinst1), TAbstract({ a_path = ["cs"],"Pointer" }, [tinst2]) when type_iseq gen tinst1 (gen.greal_type tinst2) ->
-							run expr
-						| _ ->
-							let expr = run expr in
-							let last_unsafe = gen.gon_unsafe_cast in
-							gen.gon_unsafe_cast <- (fun t t2 pos -> ());
-							let ret = handle expr e.etype expr.etype in
-							gen.gon_unsafe_cast <- last_unsafe;
-							match ret.eexpr with
-								| TCast _ -> { ret with etype = gen.greal_type e.etype }
-								| _ -> { e with eexpr = TCast(ret,md); etype = gen.greal_type e.etype }
-				)
-			(*| TCast _ ->
-				(* if there is already a cast, we should skip this cast check *)
-				Type.map_expr run e*)
-			| TFunction f ->
-				in_value := false;
-				Type.map_expr run e
-
-			| _ -> Type.map_expr run e
-	in
-	gen.ghandle_cast <- (fun tto tfrom expr -> handle_cast gen expr (gen.greal_type tto) (gen.greal_type tfrom));
-	let map e =
-		match gen.gcurrent_classfield with
-		| Some cf when Meta.has (Meta.Custom ":skipCastDetect") cf.cf_meta ->
-			e
-		| _ ->
-			run e
-	in
-	gen.gsyntax_filters#add name (PCustom priority) map;
-	ReturnCast.configure gen

+ 0 - 57
src/codegen/gencommon/classInstance.ml

@@ -1,57 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Type
-open Gencommon
-
-(*
-	When we pass a class as an object, in some languages we will need a special construct to be able to
-	access its statics as if they were normal object fields. On C# and Java the way found to do that is
-	by handling statics reflection also by a normal instance. This also happens in hxcpp and neko, so I
-	guess it's a valid practice.
-
-	So if we want to handle the reflection of the static MyClass, here's roughly how it will be done:
-
-	var x = MyClass;
-	gets converted into
-	var x = typeof(MyClass);
-*)
-let add_typeof =
-	let rec run e =
-		match e.eexpr with
-		| TCall (({ eexpr = TIdent ("__is__" | "__as__" | "__typeof__") } as elocal), args) ->
-			let args = List.map (fun e -> match e.eexpr with TTypeExpr _ -> e | _ -> run e) args in
-			{ e with eexpr = TCall (elocal, args) }
-		| TField ({ eexpr = TTypeExpr _ }, _) ->
-			e
-		| TField (ef, f) ->
-			(match anon_class ef.etype with
-			| None -> Type.map_expr run e
-			| Some t -> { e with eexpr = TField ({ ef with eexpr = TTypeExpr t }, f)})
-		| TTypeExpr _ ->
-			{ e with eexpr = TCall (mk (TIdent "__typeof__") t_dynamic e.epos, [e]) }
-		| _ ->
-			Type.map_expr run e
-	in
-	run
-
-let name = "class_instance"
-let priority = solve_deps name []
-
-let configure gen =
-	gen.gsyntax_filters#add name (PCustom priority) add_typeof

+ 0 - 1184
src/codegen/gencommon/closuresToClass.ml

@@ -1,1184 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Common
-open Globals
-open Codegen
-open Texpr.Builder
-open Ast
-open Type
-open Gencommon
-
-(* ******************************************* *)
-(* Closures To Class *)
-(* ******************************************* *)
-(*
-
-	This is a very important filter. It will take all anonymous functions from the AST, will search for all captured variables, and will create a class
-	that implements an abstract interface for calling functions. This is very important for targets that don't support anonymous functions to work correctly.
-	Also it is possible to implement some strategies to avoid value type boxing, such as NaN tagging or double/object arguments. All this will be abstracted away
-	from this interface.
-
-
-	dependencies:
-		must run after dynamic field access, because of conflicting ways to deal with invokeField
-		(module filter) must run after OverloadingConstructor so we can also change the dynamic function expressions
-
-		uses TArray expressions for array. TODO see interaction
-		uses TThrow expressions.
-*)
-let name = "closures_to_class"
-let priority = solve_deps name [ DAfter DynamicFieldAccess.priority ]
-
-type closures_ctx = {
-	func_class : tclass;
-
-	(*
-		this is what will actually turn the function into class field.
-		The standard implementation by default will already take care of creating the class, and setting the captured variables.
-
-		It will also return the super arguments to be called
-	*)
-	closure_to_classfield : tfunc->t->pos->tclass_field * (texpr list);
-
-	(*
-		when a dynamic function call is made, we need to convert it as if it were calling the dynamic function interface.
-
-		TCall expr -> new TCall expr
-	*)
-	dynamic_fun_call : texpr->texpr;
-
-	(*
-		Provide a toolchain so we can easily create classes that extend Function and add more functionality on top of it.
-
-		arguments:
-			tclass -> subject (so we know the type of this)
-			( int -> (int->t->tconstant option->texpr) -> ( (tvar * tconstant option) list * texpr) )
-				int -> current arity of the function whose member will be mapped; -1 for dynamic function. It is guaranteed that dynamic function will be called last
-				t -> the return type of the function
-				(int->t->tconstant option->texpr) -> api to get exprs that unwrap arguments correctly
-					int -> argument wanted to unwrap
-					t -> solicited type
-					tconstant option -> map to this default value if null
-					returns a texpr that tells how the default
-				should return a list with additional arguments (only works if is_function_base = true)
-				and the underlying function expression
-	*)
-	map_base_classfields : tclass->( int -> t -> (tvar list) -> (int->t->tconstant option->texpr) -> texpr )->tclass_field list;
-}
-
-type map_info = {
-	in_unsafe : bool;
-	in_unused : bool;
-}
-
-let null_map_info = { in_unsafe = false; in_unused = false; }
-
-(*
-	the default implementation will take 3 transformation functions:
-		* one that will transform closures that are not called immediately (instance.myFunc).
-			normally on this case it's best to have a runtime handler that will take the instance, the function and call its invokeField when invoked
-		* one that will actually handle the anonymous functions themselves.
-		* one that will transform calling a dynamic function. So for example, dynFunc(arg1, arg2) might turn into dynFunc.apply2(arg1, arg2);
-		( suspended ) * an option to match papplied functions
-		* handling parameterized anonymous function declaration (optional - tparam_anon_decl and tparam_anon_acc)
-*)
-
-let rec cleanup_delegate e = match e.eexpr with
-	| TParenthesis e | TMeta(_,e)
-	| TCast(e,_) -> cleanup_delegate e
-	| _ -> e
-
-let funct gen t = match follow (run_follow gen t) with
-	| TFun(args,ret) -> args,ret
-	| _ -> raise Not_found
-
-let mk_conversion_fun gen e =
-	let args, ret = funct gen e.etype in
-	let i = ref 0 in
-	let tf_args = List.map (fun (n,o,t) ->
-		let n = if n = "" then ("arg" ^ string_of_int(!i)) else n in
-		incr i;
-		alloc_var n t,None) args
-	in
-	let block, local = match e.eexpr with
-		| TLocal v ->
-			add_var_flag v VCaptured;
-			[],e
-		| _ ->
-			let tmp = mk_temp "delegate_conv" e.etype in
-			add_var_flag tmp VCaptured;
-			[{ eexpr = TVar(tmp,Some e); etype = gen.gcon.basic.tvoid; epos = e.epos }], mk_local tmp e.epos
-	in
-	let body = {
-		eexpr = TCall(local, List.map (fun (v,_) -> mk_local v e.epos) tf_args);
-		etype = ret;
-		epos = e.epos;
-	} in
-	let body = if not (ExtType.is_void ret) then
-		mk_return body
-	else
-		body
-	in
-	let body = {
-		eexpr = TBlock([body]);
-		etype = body.etype;
-		epos = body.epos;
-	} in
-	block, {
-		tf_args = tf_args;
-		tf_expr = body;
-		tf_type = ret;
-	}
-
-let traverse gen ?tparam_anon_decl ?tparam_anon_acc (handle_anon_func:texpr->tfunc->map_info->t option->texpr) (dynamic_func_call:texpr->texpr) e =
-	let info = ref null_map_info in
-	let rec run e =
-		match e.eexpr with
-			| TCast({ eexpr = TCall({ eexpr = TIdent "__delegate__" } as local, [del] ) } as e2, _) ->
-				let e2 = { e2 with etype = e.etype } in
-				let replace_delegate ex =
-					{ e with eexpr = TCast({ e2 with eexpr = TCall(local, [ex]) }, None) }
-				in
-				(* found a delegate; let's see if it's a closure or not *)
-				let clean = cleanup_delegate del in
-				(match clean.eexpr with
-					| TField( ef, (FClosure _ as f)) | TField( ef, (FStatic _ as f)) ->
-						(* a closure; let's leave this unchanged for FilterClosures to handle it *)
-						replace_delegate { clean with eexpr = TField( run ef, f ) }
-					| TFunction tf ->
-						(* handle like we'd handle a normal function, but create an unchanged closure field for it *)
-						let ret = handle_anon_func clean { tf with tf_expr = run tf.tf_expr } !info (Some e.etype) in
-						replace_delegate ret
-					| _ -> try
-						let block, tf = mk_conversion_fun gen del in
-						let block = List.map run block in
-						let tf = { tf with tf_expr = run tf.tf_expr } in
-						let ret = handle_anon_func { clean with eexpr = TFunction(tf) } { tf with tf_expr = run tf.tf_expr } !info (Some e.etype) in
-						let ret = replace_delegate ret in
-						if block = [] then
-							ret
-						else
-							{ ret with eexpr = TBlock(block @ [ret]) }
-					with Not_found ->
-						gen.gcon.error "This delegate construct is unsupported" e.epos;
-						replace_delegate (run clean))
-
-			| TCall(({ eexpr = TIdent "__unsafe__" } as local), [arg]) ->
-				let old = !info in
-				info := { !info with in_unsafe = true };
-				let arg2 = run arg in
-				info := old;
-				{ e with eexpr = TCall(local,[arg2]) }
-			(* parameterized functions handling *)
-			| TVar(vv, ve) -> (match tparam_anon_decl with
-				| None -> Type.map_expr run e
-				| Some tparam_anon_decl ->
-					(match (vv, ve) with
-						| ({ v_extra = Some({v_params = _ :: _}) } as v), Some ({ eexpr = TFunction tf } as f)
-						| ({ v_extra = Some({v_params = _ :: _}) } as v), Some { eexpr = TArrayDecl([{ eexpr = TFunction tf } as f]) | TCall({ eexpr = TIdent "__array__" }, [{ eexpr = TFunction tf } as f]) } -> (* captured transformation *)
-							tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr };
-							{ e with eexpr = TBlock([]) }
-						| _ ->
-							Type.map_expr run { e with eexpr = TVar(vv, ve) })
-					)
-			| TBinop(OpAssign, { eexpr = TLocal({ v_extra = Some({v_params = _ :: _}) } as v)}, ({ eexpr= TFunction tf } as f)) when is_some tparam_anon_decl ->
-				(match tparam_anon_decl with
-					| None -> die "" __LOC__
-					| Some tparam_anon_decl ->
-						tparam_anon_decl v f { tf with tf_expr = run tf.tf_expr };
-						{ e with eexpr = TBlock([]) }
-				)
-			| TLocal ({ v_extra = Some({v_params =  _ :: _}) } as v) ->
-				(match tparam_anon_acc with
-				| None -> Type.map_expr run e
-				| Some tparam_anon_acc -> tparam_anon_acc v e false)
-			| TArray ( ({ eexpr = TLocal ({ v_extra = Some({v_params =  _ :: _}) } as v) } as expr), _) -> (* captured transformation *)
-				(match tparam_anon_acc with
-				| None -> Type.map_expr run e
-				| Some tparam_anon_acc -> tparam_anon_acc v { expr with etype = e.etype } false)
-			| TMeta((Meta.Custom ":tparamcall",_,_),({ eexpr=TLocal ({ v_extra = Some({v_params = _ :: _}) } as v) } as expr)) ->
-				(match tparam_anon_acc with
-				| None -> Type.map_expr run e
-				| Some tparam_anon_acc -> tparam_anon_acc v expr true)
-			| TCall( { eexpr = TField(_, FEnum _) }, _ ) ->
-				Type.map_expr run e
-			(* if a TClosure is being call immediately, there's no need to convert it to a TClosure *)
-			| TCall(( { eexpr = TField(ecl,f) } as e1), params) ->
-				(* check to see if called field is known and if it is a MethNormal (only MethNormal fields can be called directly) *)
-				(* let name = field_name f in *)
-				(match field_access_esp gen (gen.greal_type ecl.etype) f with
-					| FClassField(_,_,_,cf,_,_,_) ->
-						(match cf.cf_kind with
-							| Method MethNormal
-							| Method MethInline ->
-								{ e with eexpr = TCall({ e1 with eexpr = TField(run ecl, f) }, List.map run params) }
-							| _ ->
-								match gen.gfollow#run_f e1.etype with
-									| TFun _ ->
-										dynamic_func_call { e with eexpr = TCall(run e1, List.map run params) }
-									| _ ->
-										let i = ref 0 in
-										let t = TFun(List.map (fun e -> incr i; "arg" ^ (string_of_int !i), false, e.etype) params, e.etype) in
-										dynamic_func_call { e with eexpr = TCall( mk_castfast t (run e1), List.map run params ) }
-						)
-					(* | FNotFound ->
-						{ e with eexpr = TCall({ e1 with eexpr = TField(run ecl, f) }, List.map run params) }
-							(* expressions by now may have generated invalid expressions *) *)
-					| _ ->
-						match gen.gfollow#run_f e1.etype with
-							| TFun _ ->
-								dynamic_func_call { e with eexpr = TCall(run e1, List.map run params) }
-							| _ ->
-								let i = ref 0 in
-								let t = TFun(List.map (fun e -> incr i; "arg" ^ (string_of_int !i), false, e.etype) params, e.etype) in
-								dynamic_func_call { e with eexpr = TCall( mk_castfast t (run e1), List.map run params ) }
-				)
-			| TFunction tf ->
-				handle_anon_func e { tf with tf_expr = run tf.tf_expr } !info None
-			| TCall({ eexpr = TConst(TSuper) }, _) ->
-				Type.map_expr run e
-			| TCall({ eexpr = TIdent s }, args) when String.get s 0 = '_' && Hashtbl.mem gen.gspecial_vars s ->
-				Type.map_expr run e
-			| TCall(tc,params) ->
-				let i = ref 0 in
-				let may_cast = match gen.gfollow#run_f tc.etype with
-					| TFun _ -> fun e -> e
-					| _ ->
-						let t = TFun(List.map (fun e ->
-								incr i;
-								("p" ^ (string_of_int !i), false, e.etype)
-							) params, e.etype)
-						in
-						fun e -> mk_castfast t e
-				in
-				dynamic_func_call { e with eexpr = TCall(run (may_cast tc), List.map run params) }
-			| _ -> Type.map_expr run e
-	in
-
-	(match e.eexpr with
-		| TFunction(tf) -> Type.map_expr run e
-		| _ -> run e)
-
-let rec get_type_params acc t =
-	match t with
-		| TInst(( { cl_kind = KTypeParameter constraints } as cl), []) ->
-			let params = List.fold_left get_type_params acc constraints in
-			List.filter (fun t -> not (List.memq t acc)) (cl :: params) @ acc;
-		| TFun (params,tret) ->
-			List.fold_left get_type_params acc ( tret :: List.map (fun (_,_,t) -> t) params )
-		| TDynamic None ->
-			acc
-		| TDynamic (Some t) ->
-			get_type_params acc t
-		| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-				get_type_params acc ( Abstract.get_underlying_type a pl)
-		| TAnon a ->
-			PMap.fold (fun cf acc ->
-				let params = List.map (fun tp -> match follow tp.ttp_type with
-					| TInst(c,_) -> c
-					| _ -> die "" __LOC__) cf.cf_params
-				in
-				List.filter (fun t -> not (List.memq t params)) (get_type_params acc cf.cf_type)
-			) a.a_fields acc
-		| TType(_, [])
-		| TAbstract (_, [])
-		| TInst(_, [])
-		| TEnum(_, []) ->
-			acc
-		| TType(_, params)
-		| TAbstract(_, params)
-		| TEnum(_, params)
-		| TInst(_, params) ->
-			List.fold_left get_type_params acc params
-		| TMono r -> (match r.tm_type with
-			| Some t -> get_type_params acc t
-			| None -> acc)
-		| _ -> get_type_params acc (follow_once t)
-
-let get_captured expr =
-	let ret = Hashtbl.create 1 in
-	let ignored = Hashtbl.create 0 in
-
-	let params = ref [] in
-	let check_params t = params := get_type_params !params t in
-	let rec traverse expr =
-		match expr.eexpr with
-			| TFor (v, _, _) ->
-				Hashtbl.add ignored v.v_id v;
-				check_params v.v_type;
-				Type.iter traverse expr
-			| TFunction(tf) ->
-				List.iter (fun (v,_) -> Hashtbl.add ignored v.v_id v) tf.tf_args;
-				(match follow expr.etype with
-					| TFun(args,ret) ->
-						List.iter (fun (_,_,t) ->
-							check_params t
-						) args;
-						check_params ret
-					| _ -> ());
-				Type.iter traverse expr
-			| TVar (v, opt) ->
-				(match v.v_extra with
-					| Some({v_params = _ :: _}) -> ()
-					| _ ->
-						check_params v.v_type);
-				Hashtbl.add ignored v.v_id v;
-				ignore(Option.map traverse opt)
-			| TLocal { v_extra = Some({v_params = (_ :: _ )}) } ->
-				()
-			| TLocal v when has_var_flag v VCaptured ->
-				(if not (Hashtbl.mem ignored v.v_id || Hashtbl.mem ret v.v_id) then begin check_params v.v_type; Hashtbl.replace ret v.v_id expr end);
-			| _ -> Type.iter traverse expr
-	in traverse expr;
-	ret, !params
-
-(*
-	OPTIMIZEME:
-
-	Take off from Codegen the code that wraps captured variables,
-
-	traverse through all variables, looking for their use (just like local_usage)
-	three possible outcomes for captured variables:
-		- become a function member variable <- best performance.
-			Will not work on functions that can be created more than once (functions inside a loop or functions inside functions)
-			The function will have to be created on top of the block, so its variables can be filled in instead of being declared
-		- single-element array - the most compatible way, though also creates a slight overhead.
-	- we'll have some labels for captured variables:
-		- used in loop
-*)
-
-(*
-	The default implementation will impose a naming convention:
-		invoke(arity)_(o for returning object/d for returning double) when arity < max_arity
-		invoke_dynamic_(o/d) when arity > max_arity
-
-	This means that it also imposes that the dynamic function return types may only be Dynamic or Float, and all other basic types must be converted to/from it.
-*)
-let configure gen ft =
-
-	let tvar_to_cdecl = Hashtbl.create 0 in
-
-	let handle_anon_func fexpr ?tvar tfunc mapinfo delegate_type : texpr * (tclass * texpr list) =
-		let fexpr = match fexpr.eexpr with
-			| TFunction(_) ->
-				{ fexpr with eexpr = TFunction(tfunc) }
-			| _ ->
-				gen.gcon.error "Function expected" fexpr.epos;
-				fexpr
-		in
-		let in_unsafe = mapinfo.in_unsafe || match gen.gcurrent_class, gen.gcurrent_classfield with
-			| Some c, _ when Meta.has Meta.Unsafe c.cl_meta -> true
-			| _, Some cf when Meta.has Meta.Unsafe cf.cf_meta -> true
-			| _ -> false
-		in
-		(* get all captured variables it uses *)
-		let captured_ht, tparams = get_captured fexpr in
-		let captured = Hashtbl.fold (fun _ e acc -> e :: acc) captured_ht [] in
-		let captured = List.sort (fun e1 e2 -> match e1, e2 with
-			| { eexpr = TLocal v1 }, { eexpr = TLocal v2 } ->
-				compare v1.v_name v2.v_name
-			| _ -> die "" __LOC__) captured
-		in
-
-		(*let cltypes = List.map (fun cl -> (snd cl.cl_path, TInst(map_param cl, []) )) tparams in*)
-		let cltypes = List.map (fun cl -> mk_type_param (snd cl.cl_path) (TInst(cl, [])) None) tparams in
-
-		(* create a new class that extends abstract function class, with a ctor implementation that will setup all captured variables *)
-		let cfield = match gen.gcurrent_classfield with
-			| None -> "Anon"
-			| Some cf -> cf.cf_name
-		in
-		let cur_line = Lexer.get_error_line fexpr.epos in
-		let name = match tvar with
-			| None ->
-				Printf.sprintf "%s_%s_%d__Fun" (snd gen.gcurrent_path) cfield cur_line
-			| Some (v) ->
-				Printf.sprintf "%s_%s_%d__Fun" (snd gen.gcurrent_path) v.v_name cur_line
-		in
-		let path = (fst gen.gcurrent_path, name) in
-		let cls = mk_class (get gen.gcurrent_class).cl_module path tfunc.tf_expr.epos in
-		if in_unsafe then cls.cl_meta <- (Meta.Unsafe,[],null_pos) :: cls.cl_meta;
-
-		(* forward NativeGen meta for Cs target *)
-		if (Common.platform gen.gcon Cs) && not(is_hxgen (TClassDecl (get gen.gcurrent_class))) && Meta.has(Meta.NativeGen) (get gen.gcurrent_class).cl_meta then
-			cls.cl_meta <- (Meta.NativeGen,[],null_pos) :: cls.cl_meta;
-
-		if Common.defined gen.gcon Define.EraseGenerics then begin
-			cls.cl_meta <- (Meta.HaxeGeneric,[],null_pos) :: cls.cl_meta
-		end;
-		cls.cl_module <- (get gen.gcurrent_class).cl_module;
-		cls.cl_params <- cltypes;
-
-		let mk_this v pos =
-			{
-				(mk_field_access gen { eexpr = TConst TThis; etype = TInst(cls, extract_param_types cls.cl_params); epos = pos } v.v_name pos)
-				with etype = v.v_type
-			}
-		in
-
-		let mk_this_assign v pos =
-		{
-			eexpr = TBinop(OpAssign, mk_this v pos, { eexpr = TLocal(v); etype = v.v_type; epos = pos });
-			etype = v.v_type;
-			epos = pos
-		} in
-
-		(* mk_class_field name t public pos kind params *)
-		let ctor_args, ctor_sig, ctor_exprs = List.fold_left (fun (ctor_args, ctor_sig, ctor_exprs) lexpr ->
-			match lexpr.eexpr with
-				| TLocal(v) ->
-					let cf = mk_class_field v.v_name v.v_type false lexpr.epos (Var({ v_read = AccNormal; v_write = AccNormal; })) [] in
-					cls.cl_fields <- PMap.add v.v_name cf cls.cl_fields;
-					cls.cl_ordered_fields <- cf :: cls.cl_ordered_fields;
-
-					let ctor_v = alloc_var v.v_name v.v_type in
-					((ctor_v, None) :: ctor_args, (v.v_name, false, v.v_type) :: ctor_sig, (mk_this_assign v cls.cl_pos) :: ctor_exprs)
-				| _ -> die "" __LOC__
-		) ([],[],[]) captured in
-
-		(* change all captured variables to this.capturedVariable *)
-		let rec change_captured e =
-			match e.eexpr with
-				| TLocal v when has_var_flag v VCaptured && Hashtbl.mem captured_ht v.v_id ->
-					mk_this v e.epos
-				| _ -> Type.map_expr change_captured e
-		in
-		let func_expr = change_captured tfunc.tf_expr in
-
-		let invokecf, invoke_field, super_args = match delegate_type with
-			| None -> (* no delegate *)
-				let ifield, sa = ft.closure_to_classfield { tfunc with tf_expr = func_expr } fexpr.etype fexpr.epos in
-				ifield,ifield,sa
-			| Some _ ->
-				let pos = cls.cl_pos in
-				let cf = mk_class_field "Delegate" (TFun(fun_args tfunc.tf_args, tfunc.tf_type)) true pos (Method MethNormal) [] in
-				cf.cf_expr <- Some { fexpr with eexpr = TFunction { tfunc with tf_expr = func_expr }; };
-				add_class_field_flag cf CfFinal;
-				cls.cl_ordered_fields <- cf :: cls.cl_ordered_fields;
-				cls.cl_fields <- PMap.add cf.cf_name cf cls.cl_fields;
-				(* invoke function body: call Delegate function *)
-				let ibody = {
-					eexpr = TCall({
-						eexpr = TField({
-							eexpr = TConst TThis;
-							etype = TInst(cls, extract_param_types cls.cl_params);
-							epos = pos;
-						}, FInstance(cls, extract_param_types cls.cl_params, cf));
-						etype = cf.cf_type;
-						epos = pos;
-					}, List.map (fun (v,_) -> mk_local v pos) tfunc.tf_args);
-					etype = tfunc.tf_type;
-					epos = pos
-				} in
-				let ibody = if not (ExtType.is_void tfunc.tf_type) then
-					mk_return ibody
-				else
-					ibody
-				in
-				let ifield, sa = ft.closure_to_classfield { tfunc with tf_expr = ibody } fexpr.etype fexpr.epos in
-				cf,ifield,sa
-		in
-
-		(* create the constructor *)
-		(* todo properly abstract how type var is set *)
-
-		cls.cl_super <- Some(ft.func_class, []);
-		let pos = cls.cl_pos in
-		let super_call =
-		{
-			eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(ft.func_class,[]); epos = pos }, super_args);
-			etype = gen.gcon.basic.tvoid;
-			epos = pos;
-		} in
-
-		let ctor_type = (TFun(ctor_sig, gen.gcon.basic.tvoid)) in
-		let ctor = mk_class_field "new" ctor_type true cls.cl_pos (Method(MethNormal)) [] in
-		ctor.cf_expr <- Some(
-		{
-			eexpr = TFunction(
-			{
-				tf_args = ctor_args;
-				tf_type = gen.gcon.basic.tvoid;
-				tf_expr = { eexpr = TBlock(super_call :: ctor_exprs); etype = gen.gcon.basic.tvoid; epos = cls.cl_pos }
-			});
-			etype = ctor_type;
-			epos = cls.cl_pos;
-		});
-		cls.cl_constructor <- Some(ctor);
-
-		(* add invoke function to the class *)
-		cls.cl_ordered_fields <- invoke_field :: cls.cl_ordered_fields;
-		cls.cl_fields <- PMap.add invoke_field.cf_name invoke_field cls.cl_fields;
-		add_class_field_flag invoke_field CfOverride;
-
-		(match tvar with
-		| None -> ()
-		| Some ({ v_extra = Some({v_params = _ :: _}) } as v) ->
-			Hashtbl.add tvar_to_cdecl v.v_id (cls,captured)
-		| _ -> ());
-
-		(* set priority as priority + 0.00001 so that this filter runs again *)
-		gen.gadd_to_module (TClassDecl cls) (priority +. 0.000001);
-
-		(* if there are no captured variables, we can create a cache so subsequent calls don't need to create a new function *)
-		let expr, clscapt =
-			match captured, tparams with
-			| [], [] ->
-				let cache_var = mk_internal_name "hx" "current" in
-				let cache_cf = mk_class_field ~static:true cache_var (TInst(cls,[])) false func_expr.epos (Var({ v_read = AccNormal; v_write = AccNormal })) [] in
-				cls.cl_ordered_statics <- cache_cf :: cls.cl_ordered_statics;
-				cls.cl_statics <- PMap.add cache_var cache_cf cls.cl_statics;
-
-				(* if (FuncClass.hx_current != null) FuncClass.hx_current; else (FuncClass.hx_current = new FuncClass()); *)
-
-				(* let mk_static_field_access cl field fieldt pos = *)
-				let hx_current = mk_static_field_access cls cache_var (TInst(cls,[])) func_expr.epos in
-
-				let pos = func_expr.epos in
-				{ fexpr with
-					etype = hx_current.etype;
-					eexpr = TIf(
-						{
-							eexpr = TBinop(OpNotEq, hx_current, null (TInst(cls,[])) pos);
-							etype = gen.gcon.basic.tbool;
-							epos = pos;
-						},
-						hx_current,
-						Some(
-						{
-							eexpr = TBinop(OpAssign, hx_current, { fexpr with eexpr = TNew(cls, [], captured) });
-							etype = (TInst(cls,[]));
-							epos = pos;
-						}))
-				}, (cls,captured)
-			| _ ->
-				(* change the expression so it will be a new "added class" ( captured variables arguments ) *)
-				{ fexpr with eexpr = TNew(cls, List.map (fun cl -> TInst(cl,[])) tparams, List.rev captured) }, (cls,captured)
-		in
-		match delegate_type with
-		| None ->
-			expr,clscapt
-		| Some _ ->
-			{
-				eexpr = TField(expr, FClosure(Some (cls,[]),invokecf)); (* TODO: FClosure change *)
-				etype = invokecf.cf_type;
-				epos = cls.cl_pos
-			}, clscapt
-	in
-
-
-	let run = traverse
-		gen
-		~tparam_anon_decl:(fun v e fn ->
-			let _, (cls,captured) = handle_anon_func e ~tvar:v fn null_map_info None in
-			Hashtbl.add tvar_to_cdecl v.v_id (cls,captured)
-		)
-		~tparam_anon_acc:(fun v e in_tparam -> try
-			let cls, captured = Hashtbl.find tvar_to_cdecl v.v_id in
-			let captured = List.sort (fun e1 e2 -> match e1, e2 with
-				| { eexpr = TLocal v1 }, { eexpr = TLocal v2 } ->
-					compare v1.v_name v2.v_name
-				| _ -> die "" __LOC__) captured
-			in
-			let types = match v.v_extra with
-				| Some ve -> ve.v_params
-				| _ -> die "" __LOC__
-			in
-			let monos = List.map (fun _ -> mk_mono()) types in
-			let vt = match follow v.v_type with
-				| TInst(_, [v]) -> v
-				| v -> v
-			in
-			let et = match follow e.etype with
-				| TInst(_, [v]) -> v
-				| v -> v
-			in
-			let original = apply_params types monos vt in
-			unify et original;
-
-			let monos = List.map (fun t -> apply_params types (List.map (fun _ -> t_dynamic) types) t) monos in
-
-			let same_cl t1 t2 = match follow t1, follow t2 with
-				| TInst(c,_), TInst(c2,_) -> c == c2
-				| _ -> false
-			in
-			let passoc = List.map2 (fun tp m -> tp.ttp_type,m) types monos in
-			let cltparams = List.map (fun tp ->
-				try
-					snd (List.find (fun (t2,_) -> same_cl tp.ttp_type t2) passoc)
-				with | Not_found -> tp.ttp_type) cls.cl_params
-			in
-			{ e with eexpr = TNew(cls, cltparams, List.rev captured) }
-		with
-			| Not_found ->
-				if in_tparam then begin
-					gen.gwarning WGenerator "This expression may be invalid" e.epos;
-					e
-				end else
-					(* It is possible that we are recursively calling a function
-					   that has type parameters. In this case, we must leave it be
-					   because as soon as the new class is added to the module,
-					   this filter will run again. By this time, the tvar-to-cdecl
-					   hashtable will be already filled with all functions, so
-					   it should run correctly. In this case, if it keeps failing.
-					   we will add the "Expression may be invalid warning" like we did
-					   before (see Issue #7118) *)
-					{ e with eexpr = TMeta(
-						(Meta.Custom(":tparamcall"), [], e.epos), e
-					) }
-			| Unify_error el ->
-				List.iter (fun el -> gen.gwarning WGenerator (Error.unify_error_msg (print_context()) el) e.epos) el;
-				gen.gwarning WGenerator "This expression may be invalid" e.epos;
-				e
-		)
-		(* (handle_anon_func:texpr->tfunc->texpr) (dynamic_func_call:texpr->texpr->texpr list->texpr) *)
-		(fun e f info delegate_type -> fst (handle_anon_func e f info delegate_type))
-		ft.dynamic_fun_call
-		(* (dynamic_func_call:texpr->texpr->texpr list->texpr) *)
-	in
-	gen.gexpr_filters#add name (PCustom priority) run
-
-(*
-	this submodule will provide the default implementation for the C# and Java targets.
-
-	it will have two return types: double and dynamic, and
-*)
-module DoubleAndDynamicClosureImpl =
-struct
-	let get_ctx gen parent_func_class max_arity mk_arg_exception (* e.g. new haxe.lang.ClassClosure *) =
-		let basic = gen.gcon.basic in
-
-		let func_args_i i =
-			let rec loop i (acc) =
-				if i = 0 then (acc) else begin
-					let vfloat = alloc_var (mk_internal_name "fn" ("float" ^ string_of_int i)) basic.tfloat in
-					let vdyn = alloc_var (mk_internal_name "fn" ("dyn" ^ string_of_int i)) t_dynamic in
-
-					loop (i - 1) ((vfloat, None) :: (vdyn, None) :: acc)
-				end
-			in
-			loop i []
-		in
-
-		let args_real_to_func args =
-			let arity = List.length args in
-			if arity >= max_arity then
-				[ alloc_var (mk_internal_name "fn" "dynargs") (gen.gclasses.nativearray t_dynamic), None ]
-			else func_args_i arity
-		in
-
-		let func_sig_i i =
-			let rec loop i acc =
-				if i = 0 then acc else begin
-					let vfloat = mk_internal_name "fn" ("float" ^ string_of_int i) in
-					let vdyn = mk_internal_name "fn" ("dyn" ^ string_of_int i) in
-
-					loop (i - 1) ( (vfloat,false,basic.tfloat) :: (vdyn,false,t_dynamic) :: acc )
-				end
-			in
-			loop i []
-		in
-
-		let args_real_to_func_sig args =
-			let arity = List.length args in
-			if arity >= max_arity then
-				[mk_internal_name "fn" "dynargs", false, gen.gclasses.nativearray t_dynamic]
-			else begin
-				func_sig_i arity
-			end
-		in
-
-		let rettype_real_to_func t = match run_follow gen t with
-			| TAbstract({ a_path = [],"Null" }, _) ->
-				0,t_dynamic
-			| _ when like_float t && not (like_i64 t) ->
-				(1, basic.tfloat)
-			| _ ->
-				(0, t_dynamic)
-		in
-
-		let args_real_to_func_call el (pos:pos) =
-			if List.length el >= max_arity then
-				[mk_nativearray_decl gen t_dynamic el pos]
-			else begin
-				List.fold_left (fun acc e ->
-					if like_float (gen.greal_type e.etype) && not (like_i64 (gen.greal_type e.etype)) then
-						( e :: undefined e.epos :: acc )
-					else
-						( null basic.tfloat e.epos :: e :: acc )
-				) ([]) (List.rev el)
-			end
-		in
-
-		let get_args_func args changed_args pos =
-			let arity = List.length args in
-			let mk_const const elocal t =
-				match const with
-				| None ->
-					mk_cast t elocal
-				| Some const ->
-					{ eexpr = TIf(
-						{ elocal with eexpr = TBinop(Ast.OpEq, elocal, null elocal.etype elocal.epos); etype = basic.tbool },
-						const,
-						Some ( mk_cast t elocal )
-					); etype = t; epos = elocal.epos }
-			in
-
-			if arity >= max_arity then begin
-				let varray = match changed_args with | [v,_] -> v | _ -> die "" __LOC__ in
-				let varray_local = mk_local varray pos in
-				let mk_varray i = { eexpr = TArray(varray_local, make_int gen.gcon.basic i pos); etype = t_dynamic; epos = pos } in
-				let el =
-					snd (List.fold_left (fun (count,acc) (v,const) ->
-						(count + 1, (mk (TVar(v, Some(mk_const const (mk_varray count) v.v_type))) basic.tvoid pos) :: acc)
-					) (0, []) args)
-				in
-				List.rev el
-			end else begin
-				let _, dyn_args, float_args = List.fold_left (fun (count,fargs, dargs) arg ->
-					if count land 1 = 0 then
-						(count + 1, fargs, arg :: dargs)
-					else
-						(count + 1, arg :: fargs, dargs)
-				) (1,[],[]) (List.rev changed_args) in
-
-				let rec loop acc args fargs dargs =
-					match args, fargs, dargs with
-						| [], [], [] -> acc
-						| (v,const) :: args, (vf,_) :: fargs, (vd,_) :: dargs ->
-							let acc = { eexpr = TVar(v, Some(
-								{
-									eexpr = TIf(
-										{ eexpr = TBinop(Ast.OpEq, mk_local vd pos, undefined pos); etype = basic.tbool; epos = pos },
-										mk_cast v.v_type (mk_local vf pos),
-										Some ( mk_const const (mk_local vd pos) v.v_type )
-									);
-									etype = v.v_type;
-									epos = pos
-								} )); etype = basic.tvoid; epos = pos } :: acc in
-							loop acc args fargs dargs
-						| _ -> die "" __LOC__
-				in
-
-				loop [] args float_args dyn_args
-			end
-		in
-
-		let closure_to_classfield tfunc old_sig pos =
-			(* change function signature *)
-			let old_args = tfunc.tf_args in
-			let changed_args = args_real_to_func old_args in
-
-			(*
-				FIXME properly handle int64 cases, which will break here (because of inference to int)
-				UPDATE: the fix will be that Int64 won't be a typedef to Float/Int
-			*)
-			let changed_sig, arity, type_number, changed_sig_ret, is_void, is_dynamic_func = match follow old_sig with
-				| TFun(_sig, ret) ->
-					let type_n, ret_t = rettype_real_to_func ret in
-					let arity = List.length _sig in
-					let is_dynamic_func = arity >= max_arity in
-					let ret_t = if is_dynamic_func then t_dynamic else ret_t in
-
-					(TFun(args_real_to_func_sig _sig, ret_t), arity, type_n, ret_t, ExtType.is_void ret, is_dynamic_func)
-				| _ -> (print_endline (s_type (print_context()) (follow old_sig) )); die "" __LOC__
-			in
-
-			let tf_expr = if is_void then begin
-				let rec map e =
-					match e.eexpr with
-						| TReturn None ->
-							mk_return (null t_dynamic e.epos)
-						| _ -> Type.map_expr map e
-				in
-				let e = mk_block (map tfunc.tf_expr) in
-				match e.eexpr with
-					| TBlock bl -> { e with eexpr = TBlock (bl @ [mk_return (null t_dynamic e.epos)]) }
-					| _ -> die "" __LOC__
-			end else tfunc.tf_expr in
-
-			let changed_sig_ret = if is_dynamic_func then t_dynamic else changed_sig_ret in
-
-			(* get real arguments on top of function body *)
-			let get_args = get_args_func tfunc.tf_args changed_args pos in
-			(*
-				FIXME HACK: in order to be able to run the filters that have already ran for this piece of code,
-				we will cheat and run it as if it was the whole code
-				We could just make ClosuresToClass run before TArrayTransform, but we cannot because of the
-				dependency between ClosuresToClass (after DynamicFieldAccess, and before TArrayTransform)
-
-				maybe a way to solve this would be to add an "until" field to run_from
-			*)
-			let real_get_args = gen.gexpr_filters#run (mk (TBlock get_args) basic.tvoid pos) in
-
-			let func_expr = Type.concat real_get_args tf_expr in
-
-			(* set invoke function *)
-			(* todo properly abstract how naming for invoke is made *)
-			let invoke_name = if is_dynamic_func then "invokeDynamic" else ("invoke" ^ (string_of_int arity) ^ (if type_number = 0 then "_o" else "_f")) in
-			let invoke_name = mk_internal_name "hx" invoke_name in
-			let invoke_field = mk_class_field invoke_name changed_sig false func_expr.epos (Method(MethNormal)) [] in
-			let invoke_fun = {
-				eexpr = TFunction {
-					tf_args = changed_args;
-					tf_type = changed_sig_ret;
-					tf_expr = func_expr;
-				};
-				etype = changed_sig;
-				epos = func_expr.epos;
-			} in
-			invoke_field.cf_expr <- Some invoke_fun;
-
-			invoke_field, [
-				make_int gen.gcon.basic arity pos;
-				make_int gen.gcon.basic type_number pos;
-			]
-		in
-
-		let dynamic_fun_call call_expr =
-			let tc, params = match call_expr.eexpr with
-				| TCall(tc, params) -> tc,wrap_rest_args gen tc.etype params tc.epos
-				| _ -> die "" __LOC__
-			in
-			let ct = gen.greal_type call_expr.etype in
-			let postfix, ret_t =
-				if like_float ct && not (like_i64 ct) then
-						"_f", gen.gcon.basic.tfloat
-				else
-					"_o", t_dynamic
-			in
-			let params_len = List.length params in
-			let ret_t = if params_len >= max_arity then t_dynamic else ret_t in
-
-			let invoke_fun = if params_len >= max_arity then "invokeDynamic" else "invoke" ^ (string_of_int params_len) ^ postfix in
-			let invoke_fun = mk_internal_name "hx" invoke_fun in
-			let fun_t = match follow tc.etype with
-				| TFun(_sig, _) ->
-					TFun(args_real_to_func_sig _sig, ret_t)
-				| _ ->
-					let i = ref 0 in
-					let _sig = List.map (fun p -> let name = "arg" ^ (string_of_int !i) in incr i; (name,false,p.etype) ) params in
-					TFun(args_real_to_func_sig _sig, ret_t)
-			in
-
-			let may_cast = match follow call_expr.etype with
-				| TAbstract ({ a_path = ([], "Void") },[]) -> (fun e -> e)
-				| _ -> mk_cast call_expr.etype
-			in
-
-			may_cast
-			{
-				eexpr = TCall(
-					{ (mk_field_access gen { tc with etype = gen.greal_type tc.etype } invoke_fun tc.epos) with etype = fun_t },
-					args_real_to_func_call params call_expr.epos
-				);
-				etype = ret_t;
-				epos = call_expr.epos
-			}
-		in
-
-		let iname i is_float =
-			let postfix = if is_float then "_f" else "_o" in
-			mk_internal_name "hx" ("invoke" ^ string_of_int i) ^ postfix
-		in
-
-		let map_base_classfields cl map_fn =
-			let pos = cl.cl_pos in
-			let this_t = TInst(cl,extract_param_types cl.cl_params) in
-			let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in
-			let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in
-
-			let mk_invoke_i i is_float =
-				let cf = mk_class_field (iname i is_float) (TFun(func_sig_i i, if is_float then basic.tfloat else t_dynamic)) false pos (Method MethNormal) [] in
-				cf
-			in
-
-			let type_name = mk_internal_name "fn" "type" in
-			let dynamic_arg = alloc_var (mk_internal_name "fn" "dynargs") (gen.gclasses.nativearray t_dynamic) in
-
-			let mk_invoke_complete_i i is_float =
-
-				(* let arity = i in *)
-				let args = func_args_i i in
-
-				(* api fn *)
-
-				(* only cast if needed *)
-				let mk_cast tto efrom = gen.ghandle_cast (gen.greal_type tto) (gen.greal_type efrom.etype) efrom in
-				let api i t const =
-					let vf, _ = List.nth args (i * 2) in
-					let vo, _ = List.nth args (i * 2 + 1) in
-
-					let needs_cast, is_float = match t, like_float t && not (like_i64 t) with
-						| TAbstract({ a_path = ([], "Float") },[]), _ -> false, true
-						| _, true -> true, true
-						| _ -> false,false
-					in
-
-					let olocal = mk_local vo pos in
-					let flocal = mk_local vf pos in
-
-					let get_from_obj e = match const with
-						| None -> mk_cast t e
-						| Some tc ->
-							{
-								eexpr = TIf(
-									{ eexpr = TBinop(Ast.OpEq, olocal, null t_dynamic pos); etype = basic.tbool; epos = pos } ,
-									{ eexpr = TConst(tc); etype = t; epos = pos },
-									Some (mk_cast t e)
-								);
-								etype = t;
-								epos = pos;
-							}
-					in
-
-					{
-						eexpr = TIf(
-							{ eexpr = TBinop(Ast.OpEq, olocal, undefined pos); etype = basic.tbool; epos = pos },
-							(if needs_cast then mk_cast t flocal else flocal),
-							Some ( get_from_obj olocal )
-						);
-						etype = t;
-						epos = pos
-					}
-				in
-				(* end of api fn *)
-
-				let ret = if is_float then basic.tfloat else t_dynamic in
-
-				let fn_expr = map_fn i ret (List.map fst args) api in
-
-				let t = TFun(fun_args args, ret) in
-
-				let tfunction =
-					{
-						eexpr = TFunction({
-							tf_args = args;
-							tf_type = ret;
-							tf_expr =
-							mk_block fn_expr
-						});
-						etype = t;
-						epos = pos;
-					}
-				in
-
-				let cf = mk_invoke_i i is_float in
-				cf.cf_expr <- Some tfunction;
-				cf
-			in
-
-			let rec loop i cfs =
-				if i < 0 then cfs else begin
-					(*let mk_invoke_complete_i i is_float =*)
-					(mk_invoke_complete_i i false) :: (mk_invoke_complete_i i true) :: (loop (i-1) cfs)
-				end
-			in
-
-			let cfs = loop max_arity [] in
-
-			let switch =
-				let api i t const =
-					match i with
-						| -1 ->
-							mk_local dynamic_arg pos
-						| _ ->
-							mk_cast t {
-								eexpr = TArray(
-									mk_local dynamic_arg pos,
-									{ eexpr = TConst(TInt(Int32.of_int i)); etype = basic.tint; epos = pos });
-								etype = t;
-								epos = pos;
-							}
-				in
-				map_fn (-1) t_dynamic [dynamic_arg] api
-			in
-
-			let args = [dynamic_arg, None] in
-			let dyn_t = TFun(fun_args args, t_dynamic) in
-			let dyn_cf = mk_class_field (mk_internal_name "hx" "invokeDynamic") dyn_t false pos (Method MethNormal) [] in
-
-			dyn_cf.cf_expr <- Some {
-				eexpr = TFunction {
-					tf_args = args;
-					tf_type = t_dynamic;
-					tf_expr = mk_block switch
-				};
-				etype = dyn_t;
-				epos = pos;
-			};
-
-			let additional_cfs = begin
-				let new_t = TFun(["arity", false, basic.tint; "type", false, basic.tint],basic.tvoid) in
-				let new_cf = mk_class_field "new" (new_t) true pos (Method MethNormal) [] in
-				let v_arity, v_type = alloc_var "arity" basic.tint, alloc_var "type" basic.tint in
-				let mk_assign v field = mk (TBinop (OpAssign, mk_this field v.v_type, mk_local v pos)) v.v_type pos in
-
-				let arity_name = mk_internal_name "hx" "arity" in
-				new_cf.cf_expr <- Some {
-					eexpr = TFunction({
-						tf_args = [v_arity, None; v_type, None];
-						tf_type = basic.tvoid;
-						tf_expr =
-						{
-							eexpr = TBlock([
-								mk_assign v_type type_name;
-								mk_assign v_arity arity_name
-							]);
-							etype = basic.tvoid;
-							epos = pos;
-						}
-					});
-					etype = new_t;
-					epos = pos;
-				};
-
-				[
-					new_cf;
-					mk_class_field type_name basic.tint true pos (Var { v_read = AccNormal; v_write = AccNormal }) [];
-					mk_class_field arity_name basic.tint true pos (Var { v_read = AccNormal; v_write = AccNormal }) [];
-				]
-			end in
-
-			dyn_cf :: (additional_cfs @ cfs)
-		in
-
-		begin
-			(*
-				setup fields for the abstract implementation of the Function class
-
-				new(arity, type)
-				{
-					this.arity = arity;
-					this.type = type;
-				}
-
-				hx::invokeX_f|o (where X is from 0 to max_arity) (args)
-				{
-					if (this.type == 0|1) return invokeX_o|f(args); else throw "Invalid number of arguments."
-				}
-
-				hx::invokeDynamic, which will work in the same way
-			*)
-			let cl = parent_func_class in
-			let pos = cl.cl_pos in
-
-			let rec mk_dyn_call arity api =
-				let zero = make_float gen.gcon.basic "0.0" pos in
-				let rec loop i acc =
-					if i = 0 then
-						acc
-					else begin
-						let arr = api (i - 1) t_dynamic None in
-						loop (i - 1) (zero :: arr :: acc)
-					end
-				in
-				loop arity []
-			in
-
-			let this = mk (TConst TThis) (TInst (cl, extract_param_types cl.cl_params)) pos in
-			let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in
-
-			let mk_invoke_switch i api =
-				let t = TFun (func_sig_i i, t_dynamic) in
-				(* case i: return this.invokeX_o(0, 0, 0, 0, 0, ... arg[0], args[1]....); *)
-				[make_int gen.gcon.basic i pos], mk_return (mk (TCall(mk_this (iname i false) t, mk_dyn_call i api)) t_dynamic pos)
-			in
-			let rec loop_cases api arity acc =
-				if arity < 0 then
-					acc
-				else
-					loop_cases api (arity - 1) (mk_invoke_switch arity api :: acc)
-			in
-
-			let type_name = mk_internal_name "fn" "type" in
-			let mk_expr i is_float vars =
-				let call_expr =
-					let call_t = TFun(List.map (fun v -> (v.v_name, false, v.v_type)) vars, if is_float then t_dynamic else basic.tfloat) in
-					{
-						eexpr = TCall(mk_this (iname i (not is_float)) call_t, List.map (fun v -> mk_local v pos) vars);
-						etype = if is_float then t_dynamic else basic.tfloat;
-						epos = pos
-					}
-				in
-				{
-					eexpr = TIf(
-						mk (TBinop (Ast.OpNotEq, mk_this type_name basic.tint, (make_int gen.gcon.basic (if is_float then 0 else 1) pos))) basic.tbool pos,
-						make_throw (mk_arg_exception "Wrong number of arguments" pos) pos,
-						Some (mk_return call_expr)
-					);
-					etype = t_dynamic;
-					epos = pos;
-				}
-			in
-
-			let arities_processed = Hashtbl.create 10 in
-			let max_arity = ref 0 in
-
-			let map_fn cur_arity fun_ret_type vars (api:int->t->tconstant option->texpr) =
-				let is_float = like_float fun_ret_type && not (like_i64 fun_ret_type) in
-				match cur_arity with
-				| -1 ->
-					let dynargs = api (-1) t_dynamic None in
-
-					(* (dynargs == null) ? 0 : dynargs.length *)
-					let switch_cond = {
-						eexpr = TIf(
-							mk (TBinop (OpEq, dynargs, null dynargs.etype pos)) basic.tbool pos,
-							mk (TConst (TInt Int32.zero)) basic.tint pos,
-							Some (gen.gclasses.nativearray_len dynargs pos));
-						etype = basic.tint;
-						epos = pos;
-					} in
-
-					{
-						eexpr = TSwitch(
-							switch_cond,
-							loop_cases api !max_arity [],
-							Some(make_throw (mk_arg_exception "Too many arguments" pos) pos));
-						etype = basic.tvoid;
-						epos = pos;
-					}
-				| _ ->
-					if not (Hashtbl.mem arities_processed cur_arity) then begin
-						Hashtbl.add arities_processed cur_arity true;
-						if cur_arity > !max_arity then max_arity := cur_arity
-					end;
-
-					mk_expr cur_arity is_float vars
-			in
-
-			let cfs = map_base_classfields cl map_fn in
-			List.iter (fun cf ->
-				if cf.cf_name = "new" then
-					parent_func_class.cl_constructor <- Some cf
-				else
-					parent_func_class.cl_fields <- PMap.add cf.cf_name cf parent_func_class.cl_fields
-			) cfs;
-			parent_func_class.cl_ordered_fields <- (List.filter (fun cf -> cf.cf_name <> "new") cfs) @ parent_func_class.cl_ordered_fields
-		end;
-
-		{
-			func_class = parent_func_class;
-			closure_to_classfield = closure_to_classfield;
-			dynamic_fun_call = dynamic_fun_call;
-			map_base_classfields = map_base_classfields;
-		}
-end;;

+ 0 - 132
src/codegen/gencommon/dynamicFieldAccess.ml

@@ -1,132 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Ast
-open Type
-open Gencommon
-
-(*
-	This module will filter every dynamic field access in haxe.
-
-	On platforms that do not support dynamic access, it is with this that you should
-	replace dynamic calls with x.field / Reflect.setField calls, and guess what -
-	this is the default implemenation!
-	Actually there is a problem with Reflect.setField because it returns void, which is a bad thing for us,
-	so even in the default implementation, the function call should be specified to a Reflect.setField version that returns
-	the value that was set
-
-	(TODO: should it be separated?)
-	As a plus, the default implementation adds something that doesn't hurt anybody, it looks for
-	TAnon with Statics / EnumStatics field accesses and transforms them into real static calls.
-	This means it will take this
-
-	var m = Math;
-	for (i in 0...1000) m.cos(10);
-
-	which is an optimization in dynamic platforms, but performs horribly on strongly typed platforms
-	and transform into:
-
-	var m = Math;
-	for (i in 0...1000) Math.cos(10);
-
-	depends on:
-		(ok) must run AFTER Binop/Unop handler - so Unops / Binops are already unrolled
-*)
-let name = "dynamic_field_access"
-let priority = solve_deps name [DAfter DynamicOperators.priority]
-
-(*
-	is_dynamic (expr) (field_access_expr) (field) : a function that indicates if the field access should be changed
-	change_expr (expr) (field_access_expr) (field) (setting expr) (is_unsafe) : changes the expression
-	call_expr (expr) (field_access_expr) (field) (call_params) : changes a call expression
-*)
-let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texpr->texpr->string->texpr option->bool->texpr) (call_expr:texpr->texpr->string->texpr list->texpr) =
-	let is_nondynamic_tparam fexpr f = match follow fexpr.etype with
-		| TInst({ cl_kind = KTypeParameter(tl) }, _) ->
-			List.exists (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl
-		| _ -> false
-	in
-
-	let rec run e =
-		match e.eexpr with
-		(* class types *)
-		| TField(fexpr, f) when is_nondynamic_tparam fexpr f ->
-			(match follow fexpr.etype with
-				| TInst( ({ cl_kind = KTypeParameter(tl) } as tp_cl), tp_tl) ->
-					let t = apply_params tp_cl.cl_params tp_tl (List.find (fun t -> not (is_dynamic { fexpr with etype = t } f)) tl) in
-					{ e with eexpr = TField(mk_cast t (run fexpr), f) }
-				| _ -> Globals.die "" __LOC__)
-
-		| TField(fexpr, f) when is_some (anon_class fexpr.etype) ->
-			let decl = get (anon_class fexpr.etype) in
-			let name = field_name f in
-			(try
-				match decl with
-				| TClassDecl cl ->
-					let cf = PMap.find name cl.cl_statics in
-					{ e with eexpr = TField ({ fexpr with eexpr = TTypeExpr decl }, FStatic (cl, cf)) }
-				| TEnumDecl en ->
-					let ef = PMap.find name en.e_constrs in
-					{ e with eexpr = TField ({ fexpr with eexpr = TTypeExpr decl }, FEnum (en, ef)) }
-				| TAbstractDecl _ (* abstracts don't have TFields *)
-				| TTypeDecl _ -> (* anon_class doesn't return TTypeDecl *)
-					Globals.die "" __LOC__
-			with Not_found ->
-				match f with
-				| FStatic (cl, cf) when has_class_field_flag cf CfExtern ->
-					{ e with eexpr = TField ({ fexpr with eexpr = TTypeExpr decl }, FStatic (cl, cf)) }
-				| _ ->
-					change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true)
-
-		| TField (fexpr, f) when is_dynamic fexpr f ->
-			change_expr e (run fexpr) (field_name f) None true
-
-		| TCall ({ eexpr = TField (_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "field" })) }, [obj; { eexpr = TConst (TString field) }]) ->
-			let t = match gen.greal_type obj.etype with
-			| TDynamic _ | TAnon _ | TMono _ -> t_dynamic
-			| t -> t
-			in
-			change_expr (mk_field_access gen { obj with etype = t } field obj.epos) (run obj) field None false
-
-		| TCall ({ eexpr = TField (_, FStatic({ cl_path = ([], "Reflect") }, { cf_name = "setField" } )) }, [obj; { eexpr = TConst(TString field) }; evalue]) ->
-			change_expr (mk_field_access gen obj field obj.epos) (run obj) field (Some (run evalue)) false
-
-		| TBinop (OpAssign, { eexpr = TField(fexpr, f) }, evalue) when is_dynamic fexpr f ->
-			change_expr e (run fexpr) (field_name f) (Some (run evalue)) true
-
-		| TBinop (OpAssign, { eexpr = TField(fexpr, f) }, evalue) ->
-			(match field_access_esp gen fexpr.etype f with
-			| FClassField(_,_,_,cf,false,t,_) when (try PMap.find cf.cf_name gen.gbase_class_fields == cf with Not_found -> false) ->
-				change_expr e (run fexpr) (field_name f) (Some (run evalue)) true
-			| _ ->
-				Type.map_expr run e)
-
-		| TBinop (OpAssignOp _, { eexpr = TField (fexpr, f) }, _) when is_dynamic fexpr f ->
-			Globals.die "" __LOC__ (* this case shouldn't happen *)
-		| TUnop (Increment, _, { eexpr = TField (({ eexpr = TLocal _ } as fexpr), f)})
-		| TUnop (Decrement, _, { eexpr = TField (({ eexpr = TLocal _ } as fexpr), f)}) when is_dynamic fexpr f ->
-			Globals.die "" __LOC__ (* this case shouldn't happen *)
-
-		| TCall ({ eexpr = TField (fexpr, f) }, params) when is_dynamic fexpr f && (not (is_nondynamic_tparam fexpr f)) ->
-			call_expr e (run fexpr) (field_name f) (List.map run params)
-
-		| _ ->
-			Type.map_expr run e
-	in
-	gen.gexpr_filters#add name (PCustom priority) run

+ 0 - 190
src/codegen/gencommon/dynamicOperators.ml

@@ -1,190 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Ast
-open Type
-open Codegen
-open Texpr.Builder
-open Gencommon
-
-(* ******************************************* *)
-(* Dynamic Binop/Unop handler *)
-(* ******************************************* *)
-(*
-	On some languages there is limited support for operations on
-	dynamic variables, so those operations must be changed.
-
-	There are 5 types of binary operators:
-		1 - can take any variable and returns a bool (== and !=)
-		2 - can take either a string, or a number and returns either a bool or the underlying type ( >, < for bool and + for returning its type)
-		3 - take numbers and return a number ( *, /, ...)
-		4 - take ints and return an int (bit manipulation)
-		5 - take a bool and returns a bool ( &&, || ...)
-
-	On the default implementation, type 1 and the plus function will be handled with a function call;
-	Type 2 will be handled with the parameter "compare_handler", which will do something like Reflect.compare(x1, x2);
-	Types 3, 4 and 5 will perform a cast to double, int and bool, which will then be handled normally by the platform
-
-	Unary operators are the most difficult to handle correctly.
-	With unary operators, there are 2 types:
-
-		1 - can take a number, changes and returns the result (++, --, ~)
-		2 - can take a number (-) or bool (!), and returns the result
-
-	The first case is much trickier, because it doesn't seem a good idea to change any variable to double just because it is dynamic,
-	but this is how we will handle right now.
-	something like that:
-
-	var x:Dynamic = 10;
-	x++;
-
-	will be:
-	object x = 10;
-	x = ((IConvertible)x).ToDouble(null) + 1;
-
-	depends on:
-		(syntax) must run before expression/statment normalization because it may generate complex expressions
-		must run before OverloadingConstructor due to later priority conflicts. Since ExpressionUnwrap is only
-		defined afterwards, we will set this value with absolute values
-*)
-let init com handle_strings (should_change:texpr->bool) (equals_handler:texpr->texpr->texpr) (dyn_plus_handler:texpr->texpr->texpr->texpr) (compare_handler:Ast.binop->texpr->texpr->texpr->texpr) =
-	let get_etype_one e =
-		if like_int e.etype then
-			make_int com.basic 1 e.epos
-		else
-			make_float com.basic "1.0" e.epos
-	in
-	let rec run e =
-		match e.eexpr with
-		| TBinop (OpAssignOp op, e1, e2) when should_change e -> (* e1 will never contain another TBinop *)
-			(match e1.eexpr with
-			| TLocal _ ->
-				mk_paren { e with eexpr = TBinop(OpAssign, e1, run { e with eexpr = TBinop(op, e1, e2) }) }
-			| TField _ | TArray _ ->
-				let eleft, rest =
-					match e1.eexpr with
-					| TField(ef, f) ->
-						let v = mk_temp "dynop" ef.etype in
-						{ e1 with eexpr = TField (mk_local v ef.epos, f) }, [mk (TVar (v, Some (run ef))) com.basic.tvoid ef.epos]
-					| TArray(e1a, e2a) ->
-						let v = mk_temp "dynop" e1a.etype in
-						let v2 = mk_temp "dynopi" e2a.etype in
-						{ e1 with eexpr = TArray(mk_local v e1a.epos, mk_local v2 e2a.epos) }, [
-							(mk (TVar (v, Some (run e1a))) com.basic.tvoid e1.epos);
-							(mk (TVar (v2, Some (run e2a))) com.basic.tvoid e1.epos)
-						]
-					| _ -> Globals.die "" __LOC__
-				in
-				{ e with eexpr = TBlock (rest @ [{ e with eexpr = TBinop (OpAssign, eleft, run { e with eexpr = TBinop (op, eleft, e2) }) }]) }
-			| _ ->
-				Globals.die "" __LOC__)
-
-		| TBinop (OpAssign, e1, e2)
-		| TBinop (OpInterval, e1, e2) ->
-			Type.map_expr run e
-
-		| TBinop (op, e1, e2) when should_change e ->
-			(match op with
-			| OpEq -> (* type 1 *)
-				equals_handler (run e1) (run e2)
-			| OpNotEq -> (* != -> !equals() *)
-				mk_parent (mk (TUnop (Not, Prefix, (equals_handler (run e1) (run e2)))) com.basic.tbool e.epos)
-			| OpAdd  ->
-				if handle_strings && (is_string e.etype || is_string e1.etype || is_string e2.etype) then
-					{ e with eexpr = TBinop (op, mk_cast com.basic.tstring (run e1), mk_cast com.basic.tstring (run e2)) }
-				else
-					dyn_plus_handler e (run e1) (run e2)
-			| OpGt | OpGte | OpLt | OpLte  -> (* type 2 *)
-				compare_handler op e (run e1) (run e2)
-			| OpMult | OpDiv | OpSub | OpMod -> (* always cast everything to double *)
-				let etype = (get_etype_one e).etype in
-				{ e with eexpr = TBinop (op, mk_cast etype (run e1), mk_cast etype (run e2)) }
-			| OpBoolAnd | OpBoolOr ->
-				{ e with eexpr = TBinop (op, mk_cast com.basic.tbool (run e1), mk_cast com.basic.tbool (run e2)) }
-			| OpAnd | OpOr | OpXor | OpShl | OpShr | OpUShr ->
-				{ e with eexpr = TBinop (op, mk_cast com.basic.tint (run e1), mk_cast com.basic.tint (run e2)) }
-			| OpAssign | OpAssignOp _ | OpInterval | OpArrow | OpIn | OpNullCoal ->
-				Globals.die "" __LOC__)
-
-		| TUnop (Increment as op, flag, e1)
-		| TUnop (Decrement as op, flag, e1) when should_change e ->
-			(*
-				some naming definitions:
-				* ret => the returning variable
-				* _g => the get body
-				* getvar => the get variable expr
-
-				This will work like this:
-					- if e1 is a TField, set _g = get body, getvar = (get body).varname
-					- if Prefix, return getvar = getvar + 1.0
-					- if Postfix, set ret = getvar; getvar = getvar + 1.0; ret;
-			*)
-			let one = get_etype_one e in
-			let etype = one.etype in
-			let op = (match op with Increment -> OpAdd | Decrement -> OpSub | _ -> Globals.die "" __LOC__) in
-
-			let block =
-				let vars, getvar =
-					match e1.eexpr with
-					| TField (fexpr, field) ->
-						let tmp = mk_temp "getvar" fexpr.etype in
-						let var = mk (TVar (tmp, Some (run fexpr))) com.basic.tvoid e.epos in
-						([var], mk (TField (make_local tmp fexpr.epos, field)) etype e1.epos)
-					| _ ->
-						([], e1)
-				in
-				match flag with
-				| Prefix ->
-					vars @ [
-						mk_cast etype { e with eexpr = TBinop(OpAssign, getvar, binop op (mk_cast etype getvar) one etype e.epos); etype = getvar.etype }
-					]
-				| Postfix ->
-					let ret = mk_temp "ret" etype in
-					let retlocal = make_local ret e.epos in
-					vars @ [
-						mk (TVar (ret, Some (mk_cast etype getvar))) com.basic.tvoid e.epos;
-						{ e with eexpr = TBinop (OpAssign, getvar, binop op retlocal one getvar.etype e.epos) };
-						retlocal
-					]
-			in
-			mk (TBlock block) etype e.epos
-
-	| TUnop (op, flag, e1) when should_change e ->
-		let etype = match op with
-			| Not -> com.basic.tbool
-			| Neg ->
-				if like_float e.etype || like_i64 e.etype then
-					e.etype
-				else
-					com.basic.tfloat
-			| _ -> com.basic.tint
-		in
-		mk_parent (mk (TUnop (op, flag, mk_cast etype (run e1))) etype e.epos)
-
-	| _ ->
-		Type.map_expr run e
-	in
-	run
-
-let name = "dyn_ops"
-let priority = 0.0
-
-let configure gen ~handle_strings should_change equals_handler dyn_plus_handler compare_handler =
-	let run = init gen.gcon handle_strings should_change equals_handler dyn_plus_handler compare_handler in
-	gen.gexpr_filters#add name (PCustom priority) run

+ 0 - 302
src/codegen/gencommon/enumToClass.ml

@@ -1,302 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Globals
-open Ast
-open Type
-open Codegen
-open Texpr.Builder
-open Gencommon
-
-(* ******************************************* *)
-(* EnumToClass *)
-(* ******************************************* *)
-(*
-	For languages that don't support parameterized enums and/or metadata in enums, we need to transform
-	enums into normal classes. This is done at the first module pass by creating new classes with the same
-	path inside the modules, and removing the actual enum module by setting it as en extern.
-
-	* The target must create its own strategy to deal with reflection. As it is right now, we will have a base class
-	which the class will extend, create @:$IsEnum metadata for the class, and create @:alias() metadatas for the fields,
-	with their tag order (as a string) as their alias. If you are using ReflectionCFs, then you don't have to worry
-	about that, as it's already generating all information needed by the haxe runtime.
-	so they can be
-*)
-let name = "enum_to_class"
-let priority = solve_deps name []
-
-type t = {
-	ec_tbl : (path, tclass) Hashtbl.t;
-}
-
-let new_t () = {
-	ec_tbl = Hashtbl.create 10
-}
-
-(* ******************************************* *)
-(* EnumToClassModf *)
-(* ******************************************* *)
-(*
-	The actual Module Filter that will transform the enum into a class
-
-	dependencies:
-		Should run before ReflectionCFs, in order to enable proper reflection access.
-		Should run before RealTypeParams.RealTypeParamsModf, since generic enums must be first converted to generic classes
-		It needs that the target platform implements __array__() as a shortcut to declare haxe.ds.Vector
-*)
-module EnumToClassModf =
-struct
-	let name = "enum_to_class_mod"
-	let priority = solve_deps name [DBefore ReflectionCFs.priority; DBefore RealTypeParams.RealTypeParamsModf.priority]
-
-	let pmap_exists fn pmap = try PMap.iter (fun a b -> if fn a b then raise Exit) pmap; false with | Exit -> true
-
-	let has_any_meta en =
-		let has_meta meta = List.exists (fun (m,_,_) -> match m with Meta.Custom _ -> true | _ -> false) meta in
-		has_meta en.e_meta || pmap_exists (fun _ ef -> has_meta ef.ef_meta) en.e_constrs
-
-	let convert gen t base_class base_param_class en =
-		let handle_type_params = false in (* TODO: look into this *)
-		let basic = gen.gcon.basic in
-		let pos = en.e_pos in
-
-		(* create the class *)
-		let cl = mk_class en.e_module en.e_path pos in
-		Hashtbl.add t.ec_tbl en.e_path cl;
-
-		(match Texpr.build_metadata gen.gcon.basic (TEnumDecl en) with
-			| Some expr ->
-				let cf = mk_class_field ~static:true "__meta__" expr.etype false expr.epos (Var { v_read = AccNormal; v_write = AccNormal }) [] in
-				cf.cf_expr <- Some expr;
-				cl.cl_statics <- PMap.add "__meta__" cf cl.cl_statics;
-				cl.cl_ordered_statics <- cf :: cl.cl_ordered_statics
-			| _ -> ()
-		);
-
-		let super, has_params = if Meta.has Meta.FlatEnum en.e_meta then base_class, false else base_param_class, true in
-
-		cl.cl_super <- Some(super,[]);
-		if en.e_extern then add_class_flag cl CExtern;
-		en.e_meta <- (Meta.Class, [], pos) :: en.e_meta;
-		cl.cl_module <- en.e_module;
-		cl.cl_meta <- ( Meta.Enum, [], pos ) :: cl.cl_meta;
-
-		(match gen.gcon.platform with
-			| Cs when Common.defined gen.gcon Define.CoreApiSerialize ->
-				cl.cl_meta <- ( Meta.Meta, [ (efield( (EConst (Ident "System"), null_pos ), "Serializable" ), null_pos) ], null_pos ) :: cl.cl_meta
-			| _ -> ());
-		let c_types =
-			if handle_type_params then
-				List.map (fun tp -> {tp with ttp_type=TInst (map_param (get_cl_t tp.ttp_type), [])}) en.e_params
-			else
-				[]
-		in
-
-		cl.cl_params <- c_types;
-
-		let i = ref 0 in
-		let cfs = List.map (fun name ->
-			let ef = PMap.find name en.e_constrs in
-			let pos = ef.ef_pos in
-			let old_i = !i in
-			incr i;
-
-			let cf = match follow ef.ef_type with
-				| TFun(params,ret) ->
-					let dup_types =
-						if handle_type_params then
-							List.map (fun tp -> {tp with ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) en.e_params
-						else
-							[]
-					in
-
-					let ef_type =
-						let fn, types = if handle_type_params then extract_param_type, dup_types else (fun _ -> t_dynamic), en.e_params in
-						let t = apply_params en.e_params (List.map fn types) ef.ef_type in
-						apply_params ef.ef_params (List.map fn ef.ef_params) t
-					in
-
-					let params, ret = get_fun ef_type in
-					let cf_params = if handle_type_params then dup_types @ ef.ef_params else [] in
-
-					let cf = mk_class_field name ef_type true pos (Method MethNormal) cf_params in
-					cf.cf_meta <- [];
-
-					let tf_args = List.map (fun (name,opt,t) ->  (alloc_var name t, if opt then Some (Texpr.Builder.make_null t null_pos) else None) ) params in
-					let arr_decl = mk_nativearray_decl gen t_dynamic (List.map (fun (v,_) -> mk_local v pos) tf_args) pos in
-					let expr = {
-						eexpr = TFunction({
-							tf_args = tf_args;
-							tf_type = ret;
-							tf_expr = mk_block ( mk_return { eexpr = TNew(cl,extract_param_types dup_types, [make_int gen.gcon.basic old_i pos; arr_decl] ); etype = TInst(cl, extract_param_types dup_types); epos = pos } );
-						});
-						etype = ef_type;
-						epos = pos
-					} in
-					cf.cf_expr <- Some expr;
-					cf
-				| _ ->
-					let actual_t = match follow ef.ef_type with
-						| TEnum(e, p) -> TEnum(e, List.map (fun _ -> t_dynamic) p)
-						| _ -> die "" __LOC__
-					in
-					let cf = mk_class_field name actual_t true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in
-					let args = if has_params then
-						[make_int gen.gcon.basic old_i pos; null (gen.gclasses.nativearray t_dynamic) pos]
-					else
-						[make_int gen.gcon.basic old_i pos]
-					in
-					cf.cf_meta <- [Meta.ReadOnly,[],pos];
-					cf.cf_expr <- Some {
-						eexpr = TNew(cl, List.map (fun _ -> t_empty) cl.cl_params, args);
-						etype = TInst(cl, List.map (fun _ -> t_empty) cl.cl_params);
-						epos = pos;
-					};
-					cf
-			in
-			cl.cl_statics <- PMap.add cf.cf_name cf cl.cl_statics;
-			cf
-		) en.e_names in
-		let constructs_cf = mk_class_field ~static:true "__hx_constructs" (gen.gclasses.nativearray basic.tstring) true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in
-		constructs_cf.cf_meta <- [Meta.ReadOnly,[],pos];
-		constructs_cf.cf_expr <- Some (mk_nativearray_decl gen basic.tstring (List.map (fun s -> { eexpr = TConst(TString s); etype = basic.tstring; epos = pos }) en.e_names) pos);
-
-		cl.cl_ordered_statics <- constructs_cf :: cfs @ cl.cl_ordered_statics ;
-		cl.cl_statics <- PMap.add "__hx_constructs" constructs_cf cl.cl_statics;
-
-		let getTag_cf_type = tfun [] basic.tstring in
-		let getTag_cf = mk_class_field "getTag" getTag_cf_type true pos (Method MethNormal) [] in
-		add_class_field_flag getTag_cf CfFinal;
-		getTag_cf.cf_expr <- Some {
-			eexpr = TFunction {
-				tf_args = [];
-				tf_type = basic.tstring;
-				tf_expr = mk_return (
-					let e_constructs = mk_static_field_access_infer cl "__hx_constructs" pos [] in
-					let e_this = mk (TConst TThis) (TInst (cl,[])) pos in
-					let e_index = mk_field_access gen e_this "index" pos in
-					{
-						eexpr = TArray(e_constructs,e_index);
-						etype = basic.tstring;
-						epos = pos;
-					}
-				)
-			};
-			etype = getTag_cf_type;
-			epos = pos;
-		};
-
-		cl.cl_ordered_fields <- getTag_cf :: cl.cl_ordered_fields ;
-		cl.cl_fields <- PMap.add "getTag" getTag_cf cl.cl_fields;
-		add_class_field_flag getTag_cf CfOverride;
-		cl.cl_meta <- (Meta.NativeGen,[],cl.cl_pos) :: cl.cl_meta;
-		gen.gadd_to_module (TClassDecl cl) (max_dep);
-
-		TEnumDecl en
-
-	(*
-		traverse
-			gen - gen context
-			convert_all : bool - should we convert all enums? If set, convert_if_has_meta will be ignored.
-			convert_if_has_meta : bool - should we convert only if it has meta?
-			enum_base_class : tclass - the enum base class.
-			should_be_hxgen : bool - should the created enum be hxgen?
-	*)
-	let configure gen t convert_all convert_if_has_meta enum_base_class param_enum_class =
-		let convert e = convert gen t enum_base_class param_enum_class e in
-		let run md =
-			match md with
-			| TEnumDecl e when is_hxgen md ->
-				if convert_all then
-					convert e
-				else if convert_if_has_meta && has_any_meta e then
-					convert e
-				else if not (Meta.has Meta.FlatEnum e.e_meta) then
-					convert e
-				else begin
-					(* take off the :hxgen meta from it, if there's any *)
-					e.e_meta <- List.filter (fun (n,_,_) -> not (n = Meta.HxGen)) e.e_meta;
-					md
-				end
-			| _ ->
-				md
-		in
-		gen.gmodule_filters#add name (PCustom priority) run
-end;;
-
-(* ******************************************* *)
-(* EnumToClassExprf *)
-(* ******************************************* *)
-(*
-	Enum to class Expression Filter
-
-	dependencies:
-		Should run before TArrayTransform, since it generates array access expressions
-*)
-module EnumToClassExprf =
-struct
-	let name = "enum_to_class_exprf"
-	let priority = solve_deps name [DBefore TArrayTransform.priority]
-
-	let configure gen t mk_enum_index_call =
-		let rec run e =
-			let get_converted_enum_type et =
-				let en, eparams = match follow (gen.gfollow#run_f et) with
-					| TEnum(en,p) -> en, p
-					| _ -> raise Not_found
-				in
-				let cl = Hashtbl.find t.ec_tbl en.e_path in
-				TInst(cl, eparams)
-			in
-
-			match e.eexpr with
-			| TEnumIndex f ->
-				let f = run f in
-				(try
-					mk_field_access gen {f with etype = get_converted_enum_type f.etype} "index" e.epos
-				with Not_found ->
-					mk_enum_index_call f e.epos)
-			| TCall (({eexpr = TField(_, FStatic({cl_path=[],"Type"},{cf_name="enumIndex"}))} as left), [f]) ->
-				let f = run f in
-				(try
-					mk_field_access gen {f with etype = get_converted_enum_type f.etype} "index" e.epos
-				with Not_found ->
-					{ e with eexpr = TCall(left, [f]) })
-			| TEnumParameter(f, _,i) ->
-				let f = run f in
-				(* check if en was converted to class *)
-				(* if it was, switch on tag field and change cond type *)
-				let f = try
-					{ f with etype = get_converted_enum_type f.etype }
-				with Not_found ->
-					f
-				in
-				let cond_array = { (mk_field_access gen f "params" f.epos) with etype = gen.gclasses.nativearray t_dynamic } in
-				index gen.gcon.basic cond_array i e.etype e.epos
-			| _ ->
-				Type.map_expr run e
-		in
-		gen.gexpr_filters#add name (PCustom priority) run
-
-end;;
-
-let configure gen convert_all convert_if_has_meta enum_base_class param_enum_class mk_enum_index_call =
-	let t = new_t () in
-	EnumToClassModf.configure gen t convert_all convert_if_has_meta enum_base_class param_enum_class;
-	EnumToClassExprf.configure gen t mk_enum_index_call

+ 0 - 399
src/codegen/gencommon/enumToClass2.ml

@@ -1,399 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Ast
-open Codegen
-open Texpr.Builder
-open Type
-open Gencommon
-
-let add_static c cf =
-	c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics;
-	c.cl_ordered_statics <- cf :: c.cl_ordered_statics
-
-let add_field c cf override =
-	c.cl_fields <- PMap.add cf.cf_name cf c.cl_fields;
-	c.cl_ordered_fields <- cf :: c.cl_ordered_fields;
-	if override then add_class_field_flag cf CfOverride
-
-let add_meta com en cl_enum =
-	Option.may (fun expr ->
-		let cf_meta = mk_field ~static:true "__meta__" expr.etype expr.epos expr.epos in
-		cf_meta.cf_expr <- Some expr;
-		add_static cl_enum cf_meta;
-	) (Texpr.build_metadata com.basic (TEnumDecl en));
-
-type enclasses = {
-	base : tclass;
-	ctors : (string, tclass) PMap.t;
-}
-
-module EnumToClass2Modf = struct
-	let name = "enum_to_class2_mod"
-	let priority = solve_deps name [DBefore ReflectionCFs.priority; DBefore RealTypeParams.RealTypeParamsModf.priority]
-
-	let convert gen ec_tbl base_class en =
-		let pos = en.e_pos in
-
-		(* create the class *)
-		let cl_enum = mk_class en.e_module en.e_path pos in
-		cl_enum.cl_super <- Some (base_class,[]);
-		if en.e_extern then add_class_flag cl_enum CExtern;
-		cl_enum.cl_meta <- [(Meta.Enum,[],pos); (Meta.NativeGen,[],pos)] @ cl_enum.cl_meta;
-
-		(* mark the enum that it's generated as a class *)
-		en.e_meta <- (Meta.Class,[],pos) :: en.e_meta;
-
-		(* add metadata *)
-		add_meta gen.gcon en cl_enum;
-
-		let basic = gen.gcon.basic in
-		let mk_array_decl t el p = mk_nativearray_decl gen t el p in
-
-		(* add constructs field (for reflection) *)
-		if has_feature gen.gcon "Type.getEnumConstructs" then begin
-			let e_constructs = mk_array_decl basic.tstring (List.map (fun s -> make_string gen.gcon.basic s pos) en.e_names) pos in
-			let cf_constructs = mk_field ~static:true "__hx_constructs" e_constructs.etype pos pos in
-			cf_constructs.cf_kind <- Var { v_read = AccNormal; v_write = AccNever };
-			cf_constructs.cf_meta <- (Meta.ReadOnly,[],pos) :: (Meta.Protected,[],pos) :: cf_constructs.cf_meta;
-			cf_constructs.cf_expr <- Some e_constructs;
-			add_static cl_enum cf_constructs
-		end;
-
-		(* add the class to the module *)
-		gen.gadd_to_module (TClassDecl cl_enum) max_dep;
-
-		let eparamsToString = mk_static_field_access_infer base_class "paramsToString" pos [] in
-		let eparamsGetHashCode = mk_static_field_access_infer base_class "paramsGetHashCode" pos [] in
-
-		let e_pack, e_name = en.e_path in
-		let cl_enum_t = TInst (cl_enum, []) in
-		let cf_getTag_t = tfun [] basic.tstring in
-		let cf_getParams_ret = basic.tarray (mk_anon (ref Closed)) in
-		let cf_getParams_t = tfun [] cf_getParams_ret in
-		let static_ctors = ref [] in
-		let ctors_map = ref PMap.empty in
-		let add_ctor name index =
-			let ef = PMap.find name en.e_constrs in
-			let pos = ef.ef_pos in
-
-			let cl_ctor = mk_class en.e_module (e_pack, e_name ^ "_" ^ name) pos in
-			add_class_flag cl_ctor CFinal;
-			cl_ctor.cl_super <- Some (cl_enum, []);
-			cl_ctor.cl_meta <- [
-				(Meta.Enum,[],pos);
-				(Meta.NativeGen,[],pos);
-			] @ cl_ctor.cl_meta;
-			ctors_map := PMap.add name cl_ctor !ctors_map;
-
-			gen.gadd_to_module (TClassDecl cl_ctor) max_dep;
-
-			let esuper = mk (TConst TSuper) cl_enum_t pos in
-			let etag = make_string gen.gcon.basic name pos in
-			let efields = ref [] in
-			(match follow ef.ef_type with
-				| TFun(_, _) ->
-					(* erase type params *)
-					let ef_type =
-						let t = apply_params en.e_params (List.map (fun _ -> t_dynamic) en.e_params) ef.ef_type in
-						apply_params ef.ef_params (List.map (fun _ -> t_dynamic) ef.ef_params) t
-					in
-					let params, ret = get_fun ef_type in
-
-					let cl_ctor_t = TInst (cl_ctor,[]) in
-					let other_en_v = alloc_var "en" cl_ctor_t in
-					let other_en_local = mk_local other_en_v pos in
-					let enumeq = mk_static_field_access_infer (get_cl (get_type gen ([],"Type"))) "enumEq" pos [t_dynamic] in
-					let refeq = mk_static_field_access_infer (get_cl (get_type gen (["System"],"Object"))) "ReferenceEquals" pos [] in
-
-					let param_equal_checks = ref [] in
-					let ctor_block = ref [] in
-					let ctor_args = ref [] in
-					let static_ctor_args = ref [] in
-					let ethis = mk (TConst TThis) cl_ctor_t pos in
-					List.iter (fun (n,_,t) ->
-						(* create a field for enum argument *)
-						let cf_param = mk_field n t pos pos in
-						cf_param.cf_kind <- Var { v_read = AccNormal; v_write = AccNever };
-						cf_param.cf_meta <- (Meta.ReadOnly,[],pos) :: cf_param.cf_meta;
-						add_field cl_ctor cf_param false;
-
-						(* add static constructor method argument *)
-						static_ctor_args := (alloc_var n t, None) :: !static_ctor_args;
-
-						(* generate argument field access *)
-						let efield = mk (TField (ethis, FInstance (cl_ctor, [], cf_param))) t pos in
-						efields := efield :: !efields;
-
-						(* add constructor argument *)
-						let ctor_arg_v = alloc_var n t in
-						ctor_args := (ctor_arg_v, None) :: !ctor_args;
-
-						(* generate assignment for the constructor *)
-						let assign = binop OpAssign efield (mk_local ctor_arg_v pos) t pos in
-						ctor_block := assign :: !ctor_block;
-
-						(* generate an enumEq check for the Equals method (TODO: extract this) *)
-						let eotherfield = mk (TField (other_en_local, FInstance (cl_ctor, [], cf_param))) t pos in
-						let e_enumeq_check = mk (TCall (enumeq, [efield; eotherfield])) basic.tbool pos in
-						let e_param_check =
-							mk (TIf (mk (TUnop (Not, Prefix, e_enumeq_check)) basic.tbool pos,
-							         mk_return (make_bool gen.gcon.basic false pos),
-							         None)
-							) basic.tvoid pos in
-						param_equal_checks := e_param_check :: !param_equal_checks;
-					) (List.rev params);
-
-					ctor_block := (mk (TCall(esuper,[make_int gen.gcon.basic index pos])) basic.tvoid pos) :: !ctor_block;
-
-					let cf_ctor_t = TFun (params, basic.tvoid) in
-					let cf_ctor = mk_class_field "new" cf_ctor_t true pos (Method MethNormal) [] in
-					cf_ctor.cf_expr <- Some {
-						eexpr = TFunction {
-							tf_args = !ctor_args;
-							tf_type = basic.tvoid;
-							tf_expr = mk (TBlock !ctor_block) basic.tvoid pos;
-						};
-						etype = cf_ctor_t;
-						epos = pos;
-					};
-					cl_ctor.cl_constructor <- Some cf_ctor;
-
-					let cf_toString_t = TFun ([],basic.tstring) in
-					let cf_toString = mk_class_field "toString" cf_toString_t true pos (Method MethNormal) [] in
-
-					let etoString_args = mk_array_decl t_dynamic !efields pos in
-					cf_toString.cf_expr <- Some {
-						eexpr = TFunction {
-							tf_args = [];
-							tf_type = basic.tstring;
-							tf_expr = mk_block (mk_return (
-								mk (TCall (eparamsToString, [etag; etoString_args])) basic.tstring pos
-							));
-						};
-						etype = cf_toString_t;
-						epos = pos;
-					};
-					add_field cl_ctor cf_toString true;
-
-					let cf_static_ctor = mk_class_field ~static:true name ef_type true pos (Method MethNormal) [] in
-					cf_static_ctor.cf_expr <- Some {
-						eexpr = TFunction {
-							tf_args = !static_ctor_args;
-							tf_type = ef_type;
-							tf_expr = mk_block (mk_return {eexpr = TNew(cl_ctor,[], (List.map (fun (v,_) -> mk_local v pos) !static_ctor_args)); etype = ef_type; epos = pos});
-						};
-						etype = ef_type;
-						epos = pos;
-					};
-					static_ctors := cf_static_ctor :: !static_ctors;
-
-					(* add Equals field *)
-					begin
-						let other_v = alloc_var "other" t_dynamic in
-						let eother_local = mk_local other_v pos in
-						let eas = mk (TIdent "__as__") t_dynamic pos in
-						let ecast = mk (TCall(eas,[eother_local])) cl_ctor_t pos in
-
-						let equals_exprs = ref (List.rev [
-							mk (TIf (
-								mk (TCall(refeq,[ethis;eother_local])) basic.tbool pos,
-								mk_return (make_bool gen.gcon.basic true pos),
-								None
-							)) basic.tvoid pos;
-							mk (TVar(other_en_v, Some ecast)) basic.tvoid pos;
-							mk (TIf(
-								mk (TBinop(OpEq,other_en_local,make_null cl_ctor_t pos)) basic.tbool pos,
-								mk_return (make_bool gen.gcon.basic false pos),
-								None
-							)) basic.tvoid pos;
-						]) in
-						equals_exprs := (List.rev !param_equal_checks) @ !equals_exprs;
-						equals_exprs := mk_return (make_bool gen.gcon.basic true pos) :: !equals_exprs;
-
-						let cf_Equals_t = TFun([("other",false,t_dynamic)],basic.tbool) in
-						let cf_Equals = mk_class_field "Equals" cf_Equals_t true pos (Method MethNormal) [] in
-						cf_Equals.cf_expr <- Some {
-							eexpr = TFunction {
-								tf_args = [(other_v,None)];
-								tf_type = basic.tbool;
-								tf_expr = mk (TBlock (List.rev !equals_exprs)) basic.tvoid pos;
-							};
-							etype = cf_Equals_t;
-							epos = pos;
-						};
-						add_field cl_ctor cf_Equals true;
-					end;
-
-					(* add GetHashCode field *)
-					begin
-						let cf_GetHashCode_t = TFun([],basic.tint) in
-						let cf_GetHashCode = mk_class_field "GetHashCode" cf_GetHashCode_t true pos (Method MethNormal) [] in
-						cf_GetHashCode.cf_expr <- Some {
-							eexpr = TFunction {
-								tf_args = [];
-								tf_type = basic.tint;
-								tf_expr = mk_block (mk_return (
-									mk (TCall(eparamsGetHashCode, [make_int gen.gcon.basic index pos;etoString_args])) basic.tint pos
-								));
-							};
-							etype = cf_GetHashCode_t;
-							epos = pos;
-						};
-						add_field cl_ctor cf_GetHashCode true;
-					end
-
-				| _ ->
-					let cf_ctor_t = TFun([], basic.tvoid) in
-					let cf_ctor = mk_class_field "new" cf_ctor_t true pos (Method MethNormal) [] in
-					cf_ctor.cf_expr <- Some {
-						eexpr = TFunction {
-							tf_args = [];
-							tf_type = basic.tvoid;
-							tf_expr = mk (TBlock [mk (TCall(esuper,[make_int gen.gcon.basic index pos])) basic.tvoid pos]) basic.tvoid pos;
-						};
-						etype = cf_ctor_t;
-						epos = pos;
-					};
-					cl_ctor.cl_constructor <- Some cf_ctor;
-
-					let cf_static_inst = mk_class_field ~static:true name cl_enum_t true pos (Var { v_read = AccNormal; v_write = AccNever }) [] in
-					cf_static_inst.cf_meta <- [Meta.ReadOnly,[],pos];
-					cf_static_inst.cf_expr <- Some {
-						eexpr = TNew(cl_ctor, [], []);
-						etype = cl_enum_t;
-						epos = pos;
-					};
-
-					static_ctors := cf_static_inst :: !static_ctors;
-			);
-
-			let cf_getTag = mk_class_field "getTag" cf_getTag_t true pos (Method MethNormal) [] in
-			cf_getTag.cf_expr <- Some {
-				eexpr = TFunction {
-					tf_args = [];
-					tf_type = basic.tstring;
-					tf_expr = mk_block (mk_return etag);
-				};
-				etype = cf_getTag_t;
-				epos = pos;
-			};
-			add_field cl_ctor cf_getTag true;
-
-			if !efields <> [] then begin
-				let cf_getParams = mk_class_field "getParams" cf_getParams_t true pos (Method MethNormal) [] in
-				cf_getParams.cf_expr <- Some {
-					eexpr = TFunction {
-						tf_args = [];
-						tf_type = cf_getParams_ret;
-						tf_expr = mk_block (mk_return (mk (TArrayDecl !efields) cf_getParams_ret pos));
-					};
-					etype = cf_getParams_t;
-					epos = pos;
-				};
-				add_field cl_ctor cf_getParams true
-			end
-		in
-
-
-		(* generate constructor subclasses and add static functions to create them *)
-		let i = ref 0 in
-		List.iter (fun name -> add_ctor name !i; incr i) en.e_names;
-
-		List.iter (add_static cl_enum) !static_ctors;
-
-		Hashtbl.add ec_tbl en.e_path {
-			base = cl_enum;
-			ctors = !ctors_map;
-		};
-
-		TEnumDecl en
-
-	let configure gen t enum_base_class =
-		let run md = match md with
-			| TEnumDecl e when is_hxgen md ->
-				convert gen t enum_base_class e
-			| _ ->
-				md
-		in
-		gen.gmodule_filters#add name (PCustom priority) run
-end;;
-
-
-module EnumToClass2Exprf = struct
-	let init com ec_tbl mk_enum_index_call =
-		let rec run e =
-			let get_converted_enum_classes et =
-				let en = match follow et with
-					| TEnum (en,_) -> en
-					| _ -> raise Not_found
-				in
-				Hashtbl.find ec_tbl en.e_path
-			in
-			let mk_converted_enum_index_access f =
-				let cl = (get_converted_enum_classes f.etype).base in
-				let e_enum = { f with etype = TInst (cl, []) } in
-				field e_enum "_hx_index" com.basic.tint e.epos
-			in
-			match e.eexpr with
-			| TEnumIndex f ->
-				let f = run f in
-				(try
-					mk_converted_enum_index_access f
-				with Not_found ->
-					mk_enum_index_call f e.epos)
-			| TCall ({ eexpr = TField (_, FStatic ({ cl_path = ([], "Type") }, { cf_name = "enumIndex" })) } as left, [f]) ->
-				let f = run f in
-				(try
-					mk_converted_enum_index_access f
-				with Not_found ->
-					{ e with eexpr = TCall(left, [f]) })
-			| TEnumParameter(f, ef, i) ->
-				let f = run f in
-				(* check if en was converted to class *)
-				(* if it was, switch on tag field and change cond type *)
-				let classes = get_converted_enum_classes f.etype in
-				let cl_enum = classes.base in
-				let f = { f with etype = TInst(cl_enum, []) } in
-
-				let cl_ctor = PMap.find ef.ef_name classes.ctors in
-				let ecast = mk (TCall (mk (TIdent "__as__") t_dynamic f.epos, [f])) (TInst (cl_ctor, [])) f.epos in
-
-				(match ef.ef_type with
-				| TFun (params, _) ->
-					let fname, _, _ = List.nth params i in
-					field ecast fname e.etype e.epos
-				| _ -> Globals.die "" __LOC__)
-			| _ ->
-				Type.map_expr run e
-		in
-		run
-
-	let name = "enum_to_class2_exprf"
-	let priority = solve_deps name []
-
-	let configure gen ec_tbl mk_enum_index_call =
-		let run = init gen.gcon ec_tbl mk_enum_index_call in
-		gen.gexpr_filters#add name (PCustom priority) run
-end;;
-
-let configure gen enum_base_class mk_enum_index_call =
-	let ec_tbl = Hashtbl.create 10 in
-	EnumToClass2Modf.configure gen ec_tbl enum_base_class;
-	EnumToClass2Exprf.configure gen ec_tbl mk_enum_index_call;

+ 0 - 638
src/codegen/gencommon/expressionUnwrap.ml

@@ -1,638 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Ast
-open Type
-open Gencommon
-
-(*
-	This is the most important module for source-code based targets. It will follow a convention of what's an expression and what's a statement,
-	and will unwrap statements where expressions are expected, and vice-versa.
-
-	It should be one of the first syntax filters to be applied. As a consequence, it's applied after all filters that add code to the AST, and by being
-	the first of the syntax filters, it will also have the AST retain most of the meaning of normal Haxe code. So it's easier to detect cases which are
-	side-effects free, for example
-
-	Any target can make use of this, but there is one requirement: The target must accept null to be set to any kind of variable. For example,
-	var i:Int = null; must be accepted. The best way to deal with this is to (like it's done in C#) make null equal to "default(Type)"
-
-	dependencies:
-		While it's best for Expression Unwrap to delay its execution as much as possible, since theoretically any
-		filter can return an expression that needs to be unwrapped, it is also desirable for ExpresionUnwrap to have
-		the AST as close as possible as Haxe's, so it can make some correct predictions (for example, so it can
-		more accurately know what can be side-effects-free and what can't).
-		This way, it will run slightly after the Normal priority, so if you don't say that a syntax filter must run
-		before Expression Unwrap, it will run after it.
-
-	TODO : While statement must become do / while, with the actual block inside an if for the condition, and else for 'break'
-*)
-
-(* priority: first syntax filter *)
-let priority = -10.0
-
-(*
-	We always need to rely on Blocks to be able to unwrap expressions correctly.
-	So the the standard traverse will always be based on blocks.
-	Normal block statements, like for(), while(), if(), ... will be mk_block'ed so there is always a block inside of them.
-
-		At the block level, we'll define an "add_statement" function, which will allow the current expression to
-		add statements to the block. This statement may or may not contain statements as expressions, so the texpr will be evaluated recursively before being added.
-
-		- traverse will always evaluate TBlocks
-		- for each texpr in a TBlock list,
-			check shallow type
-				if type is Statement or Both when it has problematic expression (var problematic_expr = count_problematic_expressions),
-					if we can eagerly call unwrap_statement on the whole expression (try_call_unwrap_statement), use the return expression
-					else
-						check expr_type of each underlying type (with expr_stat_map)
-							if it has ExprWithStatement or Statement,
-								call problematic_expression_unwrap in it
-								problematic_expr--
-							else if problematic_expr == 0, just add the unchanged expression
-							else if NoSideEffects and doesn't have short-circuit, just add the unchanged expression
-							else call problematic_expression_unwrap in it
-				if type is Expression, check if there are statements or Both inside.
-					if there are, problematic_expression_unwrap in it
-				aftewards, use on_expr_as_statement to get it
-
-	helpers:
-		try_call_unwrap_statement: (returns texpr option)
-			if underlying statement is TBinop(OpAssign/OpAssignOp), or TVar, with the right side being a Statement or a short circuit op, we can call apply_assign.
-
-		apply_assign:
-			if is TVar, first declare the tvar with default expression = null;
-			will receive the left and right side of the assignment; right-side must be Statement
-			see if right side is a short-circuit operation, call short_circuit_op_unwrap
-			else see eexpr of the right side
-				if it's void, just add the statement with add_statement, and set the right side as null;
-				if not, it will have a block inside. set the left side = to the last expression on each block inside. add_statement for it.
-
-		short_circuit_op_unwrap: x() && (1 + {var x = 0; x + 1;} == 2) && z()
-			-> var x = x();
-					var y = false;
-					var z = false;
-					if (x) //for &&, neg for ||
-					{
-					var temp = null;
-					{
-						var x = 0;
-						temp = x + 1;
-					}
-
-					y = (1 + temp) == 2;
-					if (y)
-					{
-						z = z();
-					}
-					}
-			expects to receive a texpr with TBinop(OpBoolAnd/OpBoolOr)
-			will traverse the AST while there is a TBinop(OpBoolAnd/OpBoolOr) as a right-side expr, and declare new temp vars in the	for each found.
-			will collect the return value, a mapped expr with all exprs as TLocal of the temp vars created
-
-
-		problematic_expression_unwrap:
-			check expr_kind:
-				if it is NoSideEffects and not short-circuit, leave it there
-				if it is ExprWithStatement and not short-circuit, call Type.map_expr problematic_expression_unwrap
-				if it is Statement or Expression or short-circuit expr, call add_assign for this expression
-
-		add_assign:
-			see if the type is void. If it is, just add_statement the expression argument, and return a null value
-			else create a new variable, set TVar with Some() with the expression argument, add TVar with add_statement, and return the TLocal of this expression.
-
-		map_problematic_expr:
-			call expr_stat_map on statement with problematic_expression_unwrap
-
-	types:
-		type shallow_expr_type = | Statement | Expression | Both (* shallow expression classification. Both means that they can be either Statements as Expressions *)
-
-		type expr_kind = | NormalExpr | ExprNoSideEffects (* -> short-circuit is considered side-effects *) | ExprWithStatement | Statement
-			evaluates an expression (as in not a statement) type. If it is ExprWithStatement or Statement, it means it contains errors
-
-	functions:
-		shallow_expr_type (expr:texpr) : shallow_expr_type
-
-		expr_kind (expr:texpr) : expr_kind
-			deeply evaluates an expression type
-
-		expr_stat_map (fn:texpr->texpr) (expr:texpr) : texpr
-			it will traverse the AST looking for places where an expression is expected, and map the value according to fn
-
-		aggregate_expr_type (is_side_effects_free:bool) (children:expr_type list) : expr_type
-			helper function to deal with expr_type aggregation (e.g. an Expression + a Statement as a children, is a ExprWithStatement)
-
-		check_statement_in_expression (expr:texpr) : texpr option :
-			will check
-
-*)
-
-type shallow_expr_type = | Statement | Expression of texpr | Both of texpr (* shallow expression classification. Both means that they can be either Statements as Expressions *)
-
-type expr_kind = | KNormalExpr | KNoSideEffects (* -> short-circuit is considered side-effects *) | KExprWithStatement | KStatement
-
-let rec no_paren e =
-	match e.eexpr with
-		| TParenthesis e -> no_paren e
-		| _ -> e
-
-(* must be called in a statement. Will execute fn whenever an expression (not statement) is expected *)
-let rec expr_stat_map fn (expr:texpr) =
-	match (no_paren expr).eexpr with
-		| TBinop ( (OpAssign as op), left_e, right_e )
-		| TBinop ( (OpAssignOp _ as op), left_e, right_e ) ->
-			{ expr with eexpr = TBinop(op, fn left_e, fn right_e) }
-		| TParenthesis _ -> Globals.die "" __LOC__
-		| TCall(left_e, params) ->
-			{ expr with eexpr = TCall(fn left_e, List.map fn params) }
-		| TNew(cl, tparams, params) ->
-			{ expr with eexpr = TNew(cl, tparams, List.map fn params) }
-		| TVar(v,eopt) ->
-			{ expr with eexpr = TVar(v, Option.map fn eopt) }
-		| TFor (v,cond,block) ->
-			{ expr with eexpr = TFor(v, fn cond, block) }
-		| TIf(cond,eif,eelse) ->
-			{ expr with eexpr = TIf(fn cond, eif, eelse) }
-		| TWhile(cond, block, flag) ->
-			{ expr with eexpr = TWhile(fn cond, block, flag) }
-		| TSwitch(cond, el_block_l, default) ->
-			{ expr with eexpr = TSwitch( fn cond, List.map (fun (el,block) -> (List.map fn el, block)) el_block_l, default ) }
-		| TReturn(eopt) ->
-			{ expr with eexpr = TReturn(Option.map fn eopt) }
-		| TThrow (texpr) ->
-			{ expr with eexpr = TThrow(fn texpr) }
-		| TBreak
-		| TContinue
-		| TTry _
-		| TUnop (Increment, _, _)
-		| TUnop (Decrement, _, _) (* unop is a special case because the haxe compiler won't let us generate complex expressions with Increment/Decrement *)
-		| TBlock _ -> expr (* there is no expected expression here. Only statements *)
-		| TMeta(m,e) ->
-			{ expr with eexpr = TMeta(m,expr_stat_map fn e) }
-		| _ -> Globals.die "" __LOC__ (* we only expect valid statements here. other expressions aren't valid statements *)
-
-let is_expr = function | Expression _ -> true | _ -> false
-
-let aggregate_expr_type map_fn side_effects_free children =
-	let rec loop acc children =
-		match children with
-			| [] -> acc
-			| hd :: children ->
-				match acc, map_fn hd with
-					| _, KExprWithStatement
-					| _, KStatement
-					| KExprWithStatement, _
-					| KStatement, _ -> KExprWithStatement
-					| KNormalExpr, KNoSideEffects
-					| KNoSideEffects, KNormalExpr
-					| KNormalExpr, KNormalExpr -> loop KNormalExpr children
-					| KNoSideEffects, KNoSideEffects -> loop KNoSideEffects children
-	in
-	loop (if side_effects_free then KNoSideEffects else KNormalExpr) children
-
-(* statements: *)
-(* Error CS0201: Only assignment, call, increment,					 *)
-(* decrement, and new object expressions can be used as a		 *)
-(* statement (CS0201). *)
-let rec shallow_expr_type expr : shallow_expr_type =
-	match expr.eexpr with
-		| TCall _ when not (ExtType.is_void expr.etype) -> Both expr
-		| TNew _
-		| TUnop (Increment, _, _)
-		| TUnop (Decrement, _, _)
-		| TBinop (OpAssign, _, _)
-		| TBinop (OpAssignOp _, _, _) -> Both expr
-		| TIf (cond, eif, Some(eelse)) -> (match aggregate_expr_type expr_kind true [cond;eif;eelse] with
-			| KExprWithStatement -> Statement
-			| _ -> Both expr)
-		| TConst _
-		| TLocal _
-		| TIdent _
-		| TArray _
-		| TBinop _
-		| TField _
-		| TEnumParameter _
-		| TEnumIndex _
-		| TTypeExpr _
-		| TObjectDecl _
-		| TArrayDecl _
-		| TFunction _
-		| TCast _
-		| TUnop _ -> Expression (expr)
-		| TParenthesis p | TMeta(_,p) -> shallow_expr_type p
-		| TBlock ([e]) -> shallow_expr_type e
-		| TCall _
-		| TVar _
-		| TBlock _
-		| TFor _
-		| TWhile _
-		| TSwitch _
-		| TTry _
-		| TReturn _
-		| TBreak
-		| TContinue
-		| TIf _
-		| TThrow _ -> Statement
-
-and expr_kind expr =
-	match shallow_expr_type expr with
-	| Statement -> KStatement
-	| Both expr | Expression expr ->
-		let aggregate = aggregate_expr_type expr_kind in
-		match expr.eexpr with
-		| TConst _
-		| TLocal _
-		| TFunction _
-		| TTypeExpr _
-		| TIdent _ ->
-			KNoSideEffects
-		| TCall (ecall, params) ->
-			aggregate false (ecall :: params)
-		| TNew (_,_,params) ->
-			aggregate false params
-		| TUnop (Increment,_,e)
-		| TUnop (Decrement,_,e) ->
-			aggregate false [e]
-		| TUnop (_,_,e) ->
-			aggregate true [e]
-		| TBinop (OpBoolAnd, e1, e2)
-		| TBinop (OpBoolOr, e1, e2) ->	(* TODO: should OpBool never be side-effects free? *)
-			aggregate true [e1;e2]
-		| TBinop (OpAssign, e1, e2)
-		| TBinop (OpAssignOp _, e1, e2) ->
-			aggregate false [e1;e2]
-		| TBinop (_, e1, e2) ->
-			aggregate true [e1;e2]
-		| TIf (cond, eif, Some(eelse)) -> (match aggregate true [cond;eif;eelse] with
-			| KExprWithStatement -> KStatement
-			| k -> k)
-		| TArray (e1,e2) ->
-			aggregate true [e1;e2]
-		| TParenthesis e
-		| TMeta(_,e)
-		| TField (e,_) ->
-			aggregate true [e]
-		| TArrayDecl (el) ->
-			aggregate true el
-		| TObjectDecl (sel) ->
-			aggregate true (List.map snd sel)
-		| TCast (e,_) ->
-			aggregate false [e]
-		| _ -> trace (debug_expr expr); Globals.die "" __LOC__ (* should have been read as Statement by shallow_expr_type *)
-
-let get_kinds (statement:texpr) =
-	let kinds = ref [] in
-	ignore (expr_stat_map (fun e ->
-		kinds := (expr_kind e) :: !kinds;
-		e
-	) statement);
-	List.rev !kinds
-
-let has_problematic_expressions (kinds:expr_kind list) =
-	let rec loop kinds =
-		match kinds with
-			| [] -> false
-			| KStatement :: _
-			| KExprWithStatement :: _ -> true
-			| _ :: tl -> loop tl
-	in
-	loop kinds
-
-let count_problematic_expressions (statement:texpr) =
-	let count = ref 0 in
-	ignore (expr_stat_map (fun e ->
-		(match expr_kind e with
-			| KStatement | KExprWithStatement -> incr count
-			| _ -> ()
-		);
-		e
-	) statement);
-	!count
-
-let apply_assign_block assign_fun elist =
-	let rec assign acc elist =
-		match elist with
-			| [] -> acc
-			| last :: [] ->
-				(assign_fun last) :: acc
-			| hd :: tl ->
-				assign (hd :: acc) tl
-	in
-	List.rev (assign [] elist)
-
-let mk_get_block assign_fun e =
-	match e.eexpr with
-		| TBlock [] -> e
-		| TBlock (el) ->
-			{ e with eexpr = TBlock(apply_assign_block assign_fun el) }
-		| _ ->
-			{ e with eexpr = TBlock([ assign_fun e ]) }
-
-let add_assign add_statement expr =
-	match expr.eexpr, follow expr.etype with
-		| _, TAbstract ({ a_path = ([],"Void") },[])
-		| TThrow _, _ ->
-			add_statement expr;
-			null expr.etype expr.epos
-		| _ ->
-			let var = mk_temp "stmt" expr.etype in
-			let tvars = { expr with eexpr = TVar(var,Some(expr)) } in
-			let local = { expr with eexpr = TLocal(var) } in
-			add_statement tvars;
-			local
-
-(* requirement: right must be a statement *)
-let rec apply_assign assign_fun right =
-	match right.eexpr with
-		| TBlock el ->
-			{ right with eexpr = TBlock(apply_assign_block assign_fun el) }
-		| TSwitch (cond, elblock_l, default) ->
-			{ right with eexpr = TSwitch(cond, List.map (fun (el,block) -> (el, mk_get_block assign_fun block)) elblock_l, Option.map (mk_get_block assign_fun) default) }
-		| TTry (block, catches) ->
-			{ right with eexpr = TTry(mk_get_block assign_fun block, List.map (fun (v,block) -> (v,mk_get_block assign_fun block) ) catches) }
-		| TIf (cond,eif,eelse) ->
-			{ right with eexpr = TIf(cond, mk_get_block assign_fun eif, Option.map (mk_get_block assign_fun) eelse) }
-		| TThrow _
-		| TWhile _
-		| TFor _
-		| TReturn _
-		| TBreak
-		| TContinue -> right
-		| TParenthesis p | TMeta(_,p) ->
-			apply_assign assign_fun p
-		| TVar _ ->
-			right
-		| _ ->
-			match follow right.etype with
-				| TAbstract ({ a_path = ([], "Void") },[]) ->
-					right
-				| _ -> trace (debug_expr right); Globals.die "" __LOC__ (* a statement is required *)
-
-let short_circuit_op_unwrap com add_statement expr :texpr =
-	let do_not expr =
-		{ expr with eexpr = TUnop(Not, Prefix, expr) }
-	in
-
-	(* loop will always return its own TBlock, and the mapped expression *)
-	let rec loop acc expr =
-		match expr.eexpr with
-			| TBinop ( (OpBoolAnd as op), left, right) ->
-				let var = mk_temp "boolv" right.etype in
-				let tvars = { right with eexpr = TVar(var, Some( { right with eexpr = TConst(TBool false); etype = com.basic.tbool } )); etype = com.basic.tvoid } in
-				let local = { right with eexpr = TLocal(var) } in
-
-				let mapped_left, ret_acc = loop ( (local, { right with eexpr = TBinop(OpAssign, local, right) } ) :: acc) left in
-
-				add_statement tvars;
-				({ expr with eexpr = TBinop(op, mapped_left, local) }, ret_acc)
-			(* we only accept OpBoolOr when it's the first to be evaluated *)
-			| TBinop ( (OpBoolOr as op), left, right) when acc = [] ->
-				let left = match left.eexpr with
-					| TLocal _ | TConst _ -> left
-					| _ -> add_assign add_statement left
-				in
-
-				let var = mk_temp "boolv" right.etype in
-				let tvars = { right with eexpr = TVar(var, Some( { right with eexpr = TConst(TBool false); etype = com.basic.tbool } )); etype = com.basic.tvoid } in
-				let local = { right with eexpr = TLocal(var) } in
-				add_statement tvars;
-
-				({ expr with eexpr = TBinop(op, left, local) }, [ do_not left, { right with eexpr = TBinop(OpAssign, local, right) } ])
-			| _ when acc = [] -> Globals.die "" __LOC__
-			| _ ->
-				let var = mk_temp "boolv" expr.etype in
-				let tvars = { expr with eexpr = TVar(var, Some( { expr with etype = com.basic.tbool } )); etype = com.basic.tvoid } in
-				let local = { expr with eexpr = TLocal(var) } in
-
-				let last_local = ref local in
-				let acc = List.map (fun (local, assign) ->
-					let l = !last_local in
-					last_local := local;
-					(l, assign)
-				) acc in
-
-				add_statement tvars;
-				(local, acc)
-	in
-
-	let mapped_expr, local_assign_list = loop [] expr in
-
-	let rec loop local_assign_list : texpr =
-		match local_assign_list with
-			| [local, assign] ->
-				{ eexpr = TIf(local, assign, None); etype = com.basic.tvoid; epos = assign.epos }
-			| (local, assign) :: tl ->
-				{ eexpr = TIf(local,
-					{
-						eexpr = TBlock ( assign :: [loop tl] );
-						etype = com.basic.tvoid;
-						epos = assign.epos;
-					},
-				None); etype = com.basic.tvoid; epos = assign.epos }
-			| [] -> Globals.die "" __LOC__
-	in
-
-	add_statement (loop local_assign_list);
-	mapped_expr
-
-let twhile_with_condition_statement com add_statement twhile cond e1 flag =
-	(* when a TWhile is found with a problematic condition *)
-	let block =
-		if flag = NormalWhile then
-			{ e1 with eexpr = TIf(cond, e1, Some({ e1 with eexpr = TBreak; etype = com.basic.tvoid })) }
-		else
-			Type.concat e1 { e1 with
-				eexpr = TIf({
-					eexpr = TUnop(Not, Prefix, mk_paren cond);
-					etype = com.basic.tbool;
-					epos = cond.epos
-				}, { e1 with eexpr = TBreak; etype = com.basic.tvoid }, None);
-				etype = com.basic.tvoid
-			}
-	in
-	add_statement { twhile with
-		eexpr = TWhile(
-			{ eexpr = TConst(TBool true); etype = com.basic.tbool; epos = cond.epos },
-			block,
-			DoWhile
-		);
-	}
-
-let try_call_unwrap_statement com handle_cast problematic_expression_unwrap (add_statement:texpr->unit) (expr:texpr) : texpr option =
-	let check_left left =
-		match expr_kind left with
-			| KExprWithStatement ->
-				problematic_expression_unwrap add_statement left KExprWithStatement
-			| KStatement -> Globals.die "" __LOC__ (* doesn't make sense a KStatement as a left side expression *)
-			| _ -> left
-	in
-
-	let handle_assign op left right =
-		let left = check_left left in
-		Some (apply_assign (fun e -> { e with eexpr = TBinop(op, left, if ExtType.is_void left.etype then e else handle_cast left.etype e.etype e) }) right )
-	in
-
-	let handle_return e =
-		Some( apply_assign (fun e ->
-			match e.eexpr with
-				| TThrow _ -> e
-				| _ when ExtType.is_void e.etype ->
-					{ e with eexpr = TBlock([e; { e with eexpr = TReturn None }]) }
-				| _ ->
-					Texpr.Builder.mk_return e
-		) e )
-	in
-
-	let is_problematic_if right =
-		match expr_kind right with
-			| KStatement | KExprWithStatement -> true
-			| _ -> false
-	in
-
-	match expr.eexpr with
-		| TBinop((OpAssign as op),left,right)
-		| TBinop((OpAssignOp _ as op),left,right) when shallow_expr_type right = Statement ->
-			handle_assign op left right
-		| TReturn( Some right ) when shallow_expr_type right = Statement ->
-			handle_return right
-		| TBinop((OpAssign as op),left, ({ eexpr = TBinop(OpBoolAnd,_,_) } as right) )
-		| TBinop((OpAssign as op),left,({ eexpr = TBinop(OpBoolOr,_,_) } as right))
-		| TBinop((OpAssignOp _ as op),left,({ eexpr = TBinop(OpBoolAnd,_,_) } as right) )
-		| TBinop((OpAssignOp _ as op),left,({ eexpr = TBinop(OpBoolOr,_,_) } as right) ) ->
-			let right = short_circuit_op_unwrap com add_statement right in
-			Some { expr with eexpr = TBinop(op, check_left left, right) }
-		| TVar(v,Some({ eexpr = TBinop(OpBoolAnd,_,_) } as right))
-		| TVar(v,Some({ eexpr = TBinop(OpBoolOr,_,_) } as right)) ->
-			let right = short_circuit_op_unwrap com add_statement right in
-			Some { expr with eexpr = TVar(v, Some(right)) }
-		| TVar(v,Some(right)) when shallow_expr_type right = Statement ->
-			add_statement ({ expr with eexpr = TVar(v, Some(null right.etype right.epos)) });
-			handle_assign OpAssign { expr with eexpr = TLocal(v); etype = v.v_type } right
-		(* TIf handling *)
-		| TBinop((OpAssign as op),left, ({ eexpr = TIf _ } as right))
-		| TBinop((OpAssignOp _ as op),left,({ eexpr = TIf _ } as right)) when is_problematic_if right ->
-			handle_assign op left right
-		| TVar(v,Some({ eexpr = TIf _ } as right)) when is_problematic_if right ->
-			add_statement ({ expr with eexpr = TVar(v, Some(null right.etype right.epos)) });
-			handle_assign OpAssign { expr with eexpr = TLocal(v); etype = v.v_type } right
-		| TWhile(cond, e1, flag) when is_problematic_if cond ->
-			twhile_with_condition_statement com add_statement expr cond e1 flag;
-			Some (null expr.etype expr.epos)
-		| _ -> None
-
-let problematic_expression_unwrap add_statement expr e_type =
-	let rec problematic_expression_unwrap is_first expr e_type =
-		match e_type, expr.eexpr with
-			| _, TBinop(OpBoolAnd, _, _)
-			| _, TBinop(OpBoolOr, _, _) -> add_assign add_statement expr (* add_assign so try_call_unwrap_expr *)
-			| KNoSideEffects, _ -> expr
-			| KStatement, _
-			| KNormalExpr, _ -> add_assign add_statement expr
-			| KExprWithStatement, TCall _
-			| KExprWithStatement, TNew _
-			| KExprWithStatement, TBinop (OpAssign,_,_)
-			| KExprWithStatement, TBinop (OpAssignOp _,_,_)
-			| KExprWithStatement, TUnop (Increment,_,_) (* all of these may have side-effects, so they must also be add_assign'ed . is_first avoids infinite loop *)
-			| KExprWithStatement, TUnop (Decrement,_,_) when not is_first -> add_assign add_statement expr
-
-			(* bugfix: Type.map_expr doesn't guarantee the correct order of execution *)
-			| KExprWithStatement, TBinop(op,e1,e2) ->
-				let e1 = problematic_expression_unwrap false e1 (expr_kind e1) in
-				let e2 = problematic_expression_unwrap false e2 (expr_kind e2) in
-				{ expr with eexpr = TBinop(op, e1, e2) }
-			| KExprWithStatement, TArray(e1,e2) ->
-				let e1 = problematic_expression_unwrap false e1 (expr_kind e1) in
-				let e2 = problematic_expression_unwrap false e2 (expr_kind e2) in
-				{ expr with eexpr = TArray(e1, e2) }
-			(* bugfix: calls should not be transformed into closure calls *)
-			| KExprWithStatement, TCall(( { eexpr = TField (ef_left, f) } as ef ), eargs) ->
-				{ expr with eexpr = TCall(
-					{ ef with eexpr = TField(problematic_expression_unwrap false ef_left (expr_kind ef_left), f) },
-					List.map (fun e -> problematic_expression_unwrap false e (expr_kind e)) eargs)
-				}
-			| KExprWithStatement, _ -> Type.map_expr (fun e -> problematic_expression_unwrap false e (expr_kind e)) expr
-	in
-	problematic_expression_unwrap true expr e_type
-
-let configure gen =
-	let rec traverse e =
-		match e.eexpr with
-		| TBlock el ->
-			let new_block = ref [] in
-			let rec process_statement e =
-				let e = no_paren e in
-				match e.eexpr, shallow_expr_type e with
-				| TCall( { eexpr = TIdent s } as elocal, elist ), _ when String.get s 0 = '_' && Hashtbl.mem gen.gspecial_vars s ->
-					new_block := { e with eexpr = TCall( elocal, List.map (fun e ->
-						match e.eexpr with
-							| TBlock _ -> traverse e
-							| _ -> e
-					) elist ) } :: !new_block
-				| _, Statement | _, Both _ ->
-					let e = match e.eexpr with TReturn (Some ({ eexpr = TThrow _ } as ethrow)) -> ethrow | _ -> e in
-					let kinds = get_kinds e in
-					if has_problematic_expressions kinds then begin
-						match try_call_unwrap_statement gen.gcon gen.ghandle_cast problematic_expression_unwrap process_statement e with
-							| Some { eexpr = TConst(TNull) } (* no op *)
-							| Some { eexpr = TBlock [] } -> ()
-							| Some e ->
-								if has_problematic_expressions (get_kinds e) then begin
-									process_statement e
-								end else
-									new_block := (traverse e) :: !new_block
-							| None ->
-							(
-								let acc = ref kinds in
-								let new_e = expr_stat_map (fun e ->
-									match !acc with
-										| hd :: tl ->
-											acc := tl;
-											if has_problematic_expressions (hd :: tl) then begin
-												problematic_expression_unwrap process_statement e hd
-											end else
-												e
-										| [] -> Globals.die "" __LOC__
-								) e in
-
-								new_block := (traverse new_e) :: !new_block
-							)
-					end else begin new_block := (traverse e) :: !new_block end
-				| _, Expression e ->
-					let e = mk (TVar (mk_temp "expr" e.etype, Some e)) gen.gcon.basic.tvoid e.epos in
-					process_statement e
-			in
-			List.iter process_statement el;
-			let block = List.rev !new_block in
-			{ e with eexpr = TBlock block }
-		| TTry (block, catches) ->
-			{ e with eexpr = TTry(traverse (mk_block block), List.map (fun (v,block) -> (v, traverse (mk_block block))) catches) }
-		| TSwitch (cond,el_e_l, default) ->
-			{ e with eexpr = TSwitch(cond, List.map (fun (el,e) -> (el, traverse (mk_block e))) el_e_l, Option.map (fun e -> traverse (mk_block e)) default) }
-		| TWhile (cond,block,flag) ->
-			{e with eexpr = TWhile(cond,traverse (mk_block block), flag) }
-		| TIf (cond, eif, eelse) ->
-			{ e with eexpr = TIf(cond, traverse (mk_block eif), Option.map (fun e -> traverse (mk_block e)) eelse) }
-		| TFor (v,it,block) ->
-			{ e with eexpr = TFor(v,it, traverse (mk_block block)) }
-		| TFunction (tfunc) ->
-			{ e with eexpr = TFunction({ tfunc with tf_expr = traverse (mk_block tfunc.tf_expr) }) }
-		| TMeta (m, e2) ->
-			{ e with eexpr = TMeta (m, traverse e2)}
-		| _ -> e (* if expression doesn't have a block, we will exit *)
-	in
-	gen.gsyntax_filters#add "expression_unwrap" (PCustom priority) traverse

+ 0 - 86
src/codegen/gencommon/filterClosures.ml

@@ -1,86 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Type
-open Gencommon
-
-(* ******************************************* *)
-(* Closure Detection *)
-(* ******************************************* *)
-(*
-	Just a small utility filter that detects when a closure must be created.
-	On the default implementation, this means when a function field is being accessed
-	not via reflection and not to be called instantly
-
-	dependencies:
-		must run after DynamicFieldAccess, so any TAnon { Statics / EnumStatics } will be changed to the corresponding TTypeExpr
-*)
-let name = "filter_closures"
-let priority = solve_deps name [DAfter DynamicFieldAccess.priority]
-
-let configure gen (should_change:texpr->string->bool) (filter:texpr->texpr->string->bool->texpr) =
-	let rec run e =
-		match e.eexpr with
-			(*(* this is precisely the only case where we won't even ask if we should change, because it is a direct use of TClosure *)
-			| TCall ( {eexpr = TClosure(e1,s)} as clos, args ) ->
-				{ e with eexpr = TCall({ clos with eexpr = TClosure(run e1, s) }, List.map run args ) }
-			| TCall ( clos, args ) ->
-				let rec loop clos = match clos.eexpr with
-					| TClosure(e1,s) -> Some (clos, e1, s)
-					| TParenthesis p -> loop p
-					| _ -> None
-				in
-				let clos = loop clos in
-				(match clos with
-					| Some (clos, e1, s) -> { e with eexpr = TCall({ clos with eexpr = TClosure(run e1, s) }, List.map run args ) }
-					| None -> Type.map_expr run e)*)
-				| TCall({ eexpr = TIdent "__delegate__" } as local, [del]) ->
-					{ e with eexpr = TCall(local, [Type.map_expr run del]) }
-				| TCall(({ eexpr = TField(_, _) } as ef), params) ->
-					{ e with eexpr = TCall(Type.map_expr run ef, List.map run params) }
-				| TField(ef, FEnum(en, field)) ->
-						(* FIXME replace t_dynamic with actual enum Anon field *)
-						let ef = run ef in
-						(match follow field.ef_type with
-							| TFun _ when should_change ef field.ef_name ->
-								filter e ef field.ef_name true
-							| _ ->
-									{ e with eexpr = TField(ef, FEnum(en,field)) }
-						)
-				| TField(({ eexpr = TTypeExpr _ } as tf), f) ->
-					(match field_access_esp gen tf.etype (f) with
-						| FClassField(_,_,_,cf,_,_,_) ->
-							(match cf.cf_kind with
-								| Method(MethDynamic)
-								| Var _ ->
-									e
-								| _ when should_change tf cf.cf_name ->
-									filter e tf cf.cf_name true
-								| _ ->
-									e
-							)
-						| _ -> e)
-				| TField(e1, FClosure (Some _, cf)) when should_change e1 cf.cf_name ->
-					(match cf.cf_kind with
-					| Method MethDynamic | Var _ ->
-						Type.map_expr run e
-					| _ ->
-						filter e (run e1) cf.cf_name false)
-				| _ -> Type.map_expr run e
-	in
-	gen.gexpr_filters#add name (PCustom priority) run

+ 0 - 276
src/codegen/gencommon/fixOverrides.ml

@@ -1,276 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Common
-open Type
-open Codegen
-open Gencommon
-
-(* ******************************************* *)
-(* FixOverrides *)
-(* ******************************************* *)
-(*
-
-	Covariant return types, contravariant function arguments and applied type parameters may change
-	in a way that expected implementations / overrides aren't recognized as such.
-	This filter will fix that.
-
-	dependencies:
-		FixOverrides expects that the target platform is able to deal with overloaded functions
-		It must run after DefaultArguments, otherwise code added by the default arguments may be invalid
-
-*)
-let name = "fix_overrides"
-let priority = solve_deps name []
-
-(*
-	if the platform allows explicit interface implementation (C#),
-	specify a explicit_fn_name function (tclass->string->string)
-	Otherwise, it expects the platform to be able to handle covariant return types
-*)
-let run ~explicit_fn_name ~get_vmtype gen =
-	let implement_explicitly = is_some explicit_fn_name in
-	let run md = match md with
-		| TClassDecl c when (has_class_flag c CInterface) && not (has_class_flag c CExtern) ->
-			(* overrides can be removed from interfaces *)
-			c.cl_ordered_fields <- List.filter (fun f ->
-				try
-					if has_class_field_flag f CfOverload then raise Not_found;
-					let f2 = Codegen.find_field gen.gcon c f in
-					if f2 == f then raise Not_found;
-					c.cl_fields <- PMap.remove f.cf_name c.cl_fields;
-					false;
-				with Not_found ->
-					true
-			) c.cl_ordered_fields;
-			md
-		| TClassDecl c when not (has_class_flag c CExtern) ->
-			let this = { eexpr = TConst TThis; etype = TInst(c,extract_param_types c.cl_params); epos = c.cl_pos } in
-			(* look through all interfaces, and try to find a type that applies exactly *)
-			let rec loop_iface (iface:tclass) itl =
-				List.iter (fun (s,stl) -> loop_iface s (List.map (apply_params iface.cl_params itl) stl)) iface.cl_implements;
-				let real_itl = gen.greal_type_param (TClassDecl iface) itl in
-				let rec loop_f f =
-					List.iter loop_f f.cf_overloads;
-					let ftype = apply_params iface.cl_params itl f.cf_type in
-					let real_ftype = get_real_fun gen (apply_params iface.cl_params real_itl f.cf_type) in
-					replace_mono real_ftype;
-					let overloads = Overloads.collect_overloads (fun t -> t) c f.cf_name in
-					try
-						let t2, f2 =
-							match overloads with
-							| (_, cf) :: _ when has_class_field_flag cf CfOverload -> (* overloaded function *)
-								(* try to find exact function *)
-								List.find (fun (t,f2) ->
-									Overloads.same_overload_args ~get_vmtype ftype t f f2
-								) overloads
-							| _ :: _ ->
-								(match field_access gen (TInst(c, extract_param_types c.cl_params)) f.cf_name with
-								| FClassField(_,_,_,f2,false,t,_) -> t,f2 (* if it's not an overload, all functions should have the same signature *)
-								| _ -> raise Not_found)
-							| [] -> raise Not_found
-						in
-						replace_mono t2;
-						(* if we find a function with the exact type of real_ftype, it means this interface has already been taken care of *)
-						if not (type_iseq (get_real_fun gen (apply_params f2.cf_params (extract_param_types f.cf_params) t2)) real_ftype) then begin
-							(match f.cf_kind with | Method (MethNormal | MethInline) -> () | _ -> raise Not_found);
-							let t2 = get_real_fun gen t2 in
-							if List.length f.cf_params <> List.length f2.cf_params then raise Not_found;
-							replace_mono t2;
-							match follow (apply_params f2.cf_params (extract_param_types f.cf_params) t2), follow real_ftype with
-							| TFun(a1,r1), TFun(a2,r2) when not implement_explicitly && not (type_iseq r1 r2) && Overloads.same_overload_args ~get_vmtype real_ftype t2 f f2 ->
-								(* different return types are the trickiest cases to deal with *)
-								(* check for covariant return type *)
-								let is_covariant = match follow r1, follow r2 with
-									| _, TDynamic _ -> false
-									| r1, r2 -> try
-										unify r1 r2;
-										if like_int r1 then like_int r2 else true
-									with | Unify_error _ -> false
-								in
-								(* we only have to worry about non-covariant issues *)
-								if not is_covariant then begin
-									(* override return type and cast implemented function *)
-									let args, newr = match follow t2, follow (apply_params f.cf_params (extract_param_types f2.cf_params) real_ftype) with
-										| TFun(a,_), TFun(_,r) -> a,r
-										| _ -> Globals.die "" __LOC__
-									in
-									f2.cf_type <- TFun(args,newr);
-									(match f2.cf_expr with
-									| Some ({ eexpr = TFunction tf } as e) ->
-											f2.cf_expr <- Some { e with eexpr = TFunction { tf with tf_type = newr } }
-									| _ -> ())
-								end
-							| TFun(a1,r1), TFun(a2,r2) ->
-								(* just implement a function that will call the main one *)
-								let name, is_explicit = match explicit_fn_name with
-									| Some fn when not (type_iseq r1 r2) && Overloads.same_overload_args ~get_vmtype real_ftype t2 f f2 ->
-											fn iface itl f.cf_name, true
-									| _ -> f.cf_name, false
-								in
-								let p = f2.cf_pos in
-								let newf = mk_class_field name real_ftype true f.cf_pos (Method MethNormal) f.cf_params in
-								(* make sure that there isn't already an overload with the same exact type *)
-								if List.exists (fun (t,f2) ->
-									type_iseq (get_real_fun gen t) real_ftype
-								) overloads then raise Not_found;
-								let vars = List.map (fun (n,_,t) -> alloc_var n t) a2 in
-
-								let args = List.map2 (fun v (_,_,t) -> mk_cast t (mk_local v f2.cf_pos)) vars a1 in
-								let field = { eexpr = TField(this, FInstance(c,extract_param_types c.cl_params,f2)); etype = TFun(a1,r1); epos = p } in
-								let call = { eexpr = TCall(field, args); etype = r1; epos = p } in
-								(* let call = gen.gparam_func_call call field (List.map snd f.cf_params) args in *)
-								let is_void = ExtType.is_void r2 in
-
-								newf.cf_expr <- Some {
-									eexpr = TFunction({
-										tf_args = List.map (fun v -> v,None) vars;
-										tf_type = r2;
-										tf_expr = if is_void then call else (Texpr.Builder.mk_return (mk_cast r2 call));
-									});
-									etype = real_ftype;
-									epos = p;
-								};
-								(try
-									let fm = PMap.find name c.cl_fields in
-									fm.cf_overloads <- newf :: fm.cf_overloads
-								with | Not_found ->
-									c.cl_fields <- PMap.add name newf c.cl_fields;
-									c.cl_ordered_fields <- newf :: c.cl_ordered_fields)
-							| _ -> Globals.die "" __LOC__
-						end
-					with | Not_found -> ()
-				in
-				List.iter (fun f -> match f.cf_kind with | Var _ -> () | _ -> loop_f f) iface.cl_ordered_fields
-			in
-			List.iter (fun (iface,itl) -> loop_iface iface itl) c.cl_implements;
-			(* now go through all overrides, *)
-			let rec check_f f =
-				(* find the first declared field *)
-				let is_overload = has_class_field_flag f CfOverload in
-				let decl = if is_overload then
-					find_first_declared_field gen c ~get_vmtype ~exact_field:f f.cf_name
-				else
-					find_first_declared_field gen c ~get_vmtype f.cf_name
-				in
-				match decl with
-				| Some(f2,actual_t,_,t,declared_cl,_,_)
-					when not (Overloads.same_overload_args ~get_vmtype actual_t (get_real_fun gen f.cf_type) f2 f) ->
-						(match f.cf_expr with
-						| Some({ eexpr = TFunction(tf) } as e) ->
-							let actual_args, _ = get_fun (get_real_fun gen actual_t) in
-							let new_args, vars_to_declare = List.fold_left2 (fun (args,vdecl) (v,_) (_,_,t) ->
-								if not (type_iseq (gen.greal_type v.v_type) (gen.greal_type t)) then begin
-									let new_var = mk_temp v.v_name t in
-									(new_var,None) :: args, (v, Some(mk_cast v.v_type (mk_local new_var f.cf_pos))) :: vdecl
-								end else
-									(v,None) :: args, vdecl
-							) ([],[]) tf.tf_args actual_args in
-							let block = { eexpr = TBlock(List.map (fun (v,ve) ->
-								{
-									eexpr = TVar(v,ve);
-									etype = gen.gcon.basic.tvoid;
-									epos = tf.tf_expr.epos
-								}) vars_to_declare);
-								etype = gen.gcon.basic.tvoid;
-								epos = tf.tf_expr.epos
-							} in
-							let has_contravariant_args = match (get_real_fun gen f.cf_type, actual_t) with
-								| TFun(current_args,_), TFun(original_args,_) ->
-										List.exists2 (fun (_,_,cur_arg) (_,_,orig_arg) -> try
-											unify orig_arg cur_arg;
-											try
-												unify cur_arg orig_arg;
-												false
-											with Unify_error _ ->
-												true
-										with Unify_error _ -> false) current_args original_args
-								| _ -> Globals.die "" __LOC__
-							in
-							if (not (has_class_field_flag f CfOverload) && has_contravariant_args) then
-								add_class_field_flag f CfOverload;
-							if has_class_field_flag f CfOverload then begin
-								(* if it is overload, create another field with the requested type *)
-								let f3 = mk_class_field f.cf_name t (has_class_field_flag f CfPublic) f.cf_pos f.cf_kind f.cf_params in
-								let p = f.cf_pos in
-								let old_args, old_ret = get_fun f.cf_type in
-								let args, ret = get_fun t in
-								let tf_args = List.rev new_args in
-								let f3_mk_return = if ExtType.is_void ret then (fun e -> e) else (fun e -> Texpr.Builder.mk_return (mk_cast ret e)) in
-								f3.cf_expr <- Some {
-									eexpr = TFunction({
-										tf_args = tf_args;
-										tf_type = ret;
-										tf_expr = Type.concat block (mk_block (f3_mk_return {
-											eexpr = TCall(
-												{
-													eexpr = TField(
-														{ eexpr = TConst TThis; etype = TInst(c, extract_param_types c.cl_params); epos = p },
-														FInstance(c,extract_param_types c.cl_params,f));
-													etype = f.cf_type;
-													epos = p
-												},
-												List.map2 (fun (v,_) (_,_,t) -> mk_cast t (mk_local v p)) tf_args old_args);
-											etype = old_ret;
-											epos = p
-										}))
-									});
-									etype = t;
-									epos = p;
-								};
-								(* make sure we skip cast detect - otherwise this new function will make the overload detection go crazy *)
-								f3.cf_meta <- (Meta.Custom(":skipCastDetect"), [], f3.cf_pos) :: f3.cf_meta;
-								gen.gafter_expr_filters_ended <- ((fun () ->
-									f.cf_overloads <- f3 :: f.cf_overloads;
-								) :: gen.gafter_expr_filters_ended);
-								f3
-							end else begin
-								(* if it's not overload, just cast the vars *)
-								if vars_to_declare <> [] then
-								f.cf_expr <- Some({ e with
-									eexpr = TFunction({ tf with
-										tf_args = List.rev new_args;
-										tf_expr = Type.concat block tf.tf_expr
-									});
-								});
-								f
-							end
-						| _ -> f)
-				| _ -> f
-			in
-			if not (has_class_flag c CExtern) then
-				List.iter (fun f ->
-					if has_class_field_flag f CfOverride then begin
-						remove_class_field_flag f CfOverride;
-						let f2 = check_f f in
-						add_class_field_flag f2 CfOverride
-					end
-				) c.cl_ordered_fields;
-			md
-		| _ -> md
-	in
-	run
-
-let configure ?explicit_fn_name ~get_vmtype gen =
-	let delay () =
-		Hashtbl.clear gen.greal_field_types
-	in
-	gen.gafter_mod_filters_ended <- delay :: gen.gafter_mod_filters_ended;
-	let run = run ~explicit_fn_name ~get_vmtype gen in
-	gen.gmodule_filters#add name (PCustom priority) run

+ 0 - 1365
src/codegen/gencommon/gencommon.ml

@@ -1,1365 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-
-(*
-	Gen Common API
-
-	This is the key module for generation of Java and C# sources
-	In order for both modules to share as much code as possible, some
-	rules were devised:
-
-	- every feature has its own submodule, and may contain the following methods:
-		- configure
-			sets all the configuration variables for the module to run. If a module has this method,
-			it *should* be called once before running any filter
-		- run_filter ->
-			runs the filter immediately on the context
-		- add_filter ->
-			adds the filter to an expr->expr list. Most filter modules will provide this option so the filter
-			function can only run once.
-	- most submodules will have side-effects so the order of operations will matter.
-		When running configure / add_filter this might be taken care of with the rule-based dispatch system working
-		underneath, but still there might be some incompatibilities. There will be an effort to document it.
-		The modules can hint on the order by suffixing their functions with _first or _last.
-	- any of those methods might have different parameters, that configure how the filter will run.
-		For example, a simple filter that maps switch() expressions to if () .. else if... might receive
-		a function that filters what content should be mapped
-	- Other targets can use those filters on their own code. In order to do that,
-		a simple configuration step is needed: you need to initialize a generator_ctx type with
-		Gencommon.new_gen (context:Common.context)
-		with a generator_ctx context you will be able to add filters to your code, and execute them with
-		Gencommon.run_filters (gen_context:Gencommon.generator_ctx)
-
-		After running the filters, you can run your own generator normally.
-
-		(* , or you can run
-		Gencommon.generate_modules (gen_context:Gencommon.generator_ctx) (extension:string) (module_gen:module_type list->bool)
-		where module_gen will take a whole module (can be *)
-*)
-open Unix
-open Ast
-open Type
-open Common
-open Globals
-open Option
-open Printf
-open ExtString
-open Codegen
-open Overloads
-
-(* ******************************************* *)
-(* common helpers *)
-(* ******************************************* *)
-
-let rec like_float t =
-	match follow t with
-	| TAbstract ({ a_path = ([], "Float") }, [])
-	| TAbstract ({ a_path = ([], "Int") }, []) ->
-		true
-	| TAbstract ({ a_path = (["cs"], "Pointer") }, _) ->
-		false
-	| TAbstract (a, _) ->
-		List.exists like_float a.a_from || List.exists like_float a.a_to
-	| _ ->
-		false
-
-let rec like_int t =
-	match follow t with
-	| TAbstract ({ a_path = ([], "Int") }, []) ->
-		true
-	| TAbstract ({ a_path = (["cs"], "Pointer") }, _) ->
-		false
-	| TAbstract (a, _) ->
-		List.exists like_int a.a_from || List.exists like_int a.a_to
-	| _ ->
-		false
-
-let rec like_i64 t =
-	match follow t with
-	| TAbstract ({ a_path = (["cs"], ("Int64" | "UInt64")) }, [])
-	| TAbstract ({ a_path = (["java"], "Int64") }, [])
-	| TAbstract ({ a_path = (["haxe"], "Int64") }, []) ->
-		true
-	| TAbstract (a, _) ->
-		List.exists like_i64 a.a_from || List.exists like_i64 a.a_to
-	| _ ->
-		false
-
-let follow_once t =
-	match t with
-	| TMono r ->
-		(match r.tm_type with
-		| Some t -> t
-		| _ -> t_dynamic) (* avoid infinite loop / should be the same in this context *)
-	| TLazy f ->
-		lazy_type f
-	| TType (t,tl) ->
-		apply_typedef t tl
-	| TAbstract({a_path = [],"Null"},[t]) ->
-		t
-	| _ ->
-		t
-
-let t_empty = mk_anon (ref Closed)
-
-let alloc_var n t = Type.alloc_var VGenerated n t null_pos
-
-let mk_local = Texpr.Builder.make_local
-
-(* the undefined is a special var that works like null, but can have special meaning *)
-let undefined =
-	(fun pos -> mk (TIdent "__undefined__") t_dynamic pos)
-
-let path_of_md_def md_def =
-	match md_def.m_types with
-		| [TClassDecl c] -> c.cl_path
-		| _ -> md_def.m_path
-
-let debug_type t = (s_type (print_context())) t
-let debug_expr = s_expr debug_type
-
-let debug_mode = ref false
-let trace s = if !debug_mode then print_endline s else ()
-let timer name = if !debug_mode then Timer.timer name else fun () -> ()
-
-let is_string t =
-	match follow t with
-	| TInst({ cl_path = ([], "String") }, []) -> true
-	| _ -> false
-
-let anon_class t =
-	match follow t with
-	| TAnon anon ->
-		(match !(anon.a_status) with
-		| Statics cl -> Some (TClassDecl cl)
-		| EnumStatics e -> Some (TEnumDecl e)
-		| AbstractStatics a -> Some (TAbstractDecl a)
-		| _ -> None)
-	| _ -> None
-
- let rec t_to_md t = match t with
-	| TInst (cl,_) -> TClassDecl cl
-	| TEnum (e,_) -> TEnumDecl e
-	| TType (t,_) -> TTypeDecl t
-	| TAbstract (a,_) -> TAbstractDecl a
-	| TAnon anon ->
-		(match !(anon.a_status) with
-			| EnumStatics e -> TEnumDecl e
-			| Statics cl -> TClassDecl cl
-			| AbstractStatics a -> TAbstractDecl a
-			| _ -> die "" __LOC__)
-	| TLazy f -> t_to_md (lazy_type f)
-	| TMono r -> (match r.tm_type with | Some t -> t_to_md t | None -> die "" __LOC__)
-	| _ -> die "" __LOC__
-
-
-let get_cl mt = match mt with TClassDecl cl -> cl | _ -> failwith (Printf.sprintf "Unexpected module type (class expected) for %s: %s" (s_type_path (t_path mt)) (s_module_type_kind mt))
-let get_abstract mt = match mt with TAbstractDecl a -> a | _ -> failwith (Printf.sprintf "Unexpected module type (abstract expected) for %s: %s" (s_type_path (t_path mt)) (s_module_type_kind mt))
-
-let get_fun t =
-	match follow t with
-	| TFun (args, ret) -> args, ret
-	| t -> (trace (debug_type t)); die "" __LOC__
-
-let mk_cast t e = Type.mk_cast e t e.epos
-
-(** TODO: when adding new AST, make a new cast type for those fast casts. For now, we're using this hack
- *        of using null_class to tell a fast cast from a normal one. Also note that this only works since both
- *        C# and Java do not use the second part of TCast for anything *)
-let mk_castfast t e = { e with eexpr = TCast(e, Some (TClassDecl null_class)); etype = t }
-
-let mk_static_field_access_infer cl field pos params =
-	try
-		let e_type = Texpr.Builder.make_static_this cl pos in
-		let cf = PMap.find field cl.cl_statics in
-		let t = if params = [] then cf.cf_type else apply_params cf.cf_params params cf.cf_type in
-		mk (TField(e_type, FStatic(cl, cf))) t pos
-	with Not_found ->
-		failwith ("Cannot find field " ^ field ^ " in class " ^ (s_type_path cl.cl_path))
-
-let mk_static_field_access cl field fieldt pos =
-	{ (mk_static_field_access_infer cl field pos []) with etype = fieldt }
-
-(* stolen from Hugh's sources ;-) *)
-(* this used to be a class, but there was something in there that crashed ocaml native compiler in windows *)
-module SourceWriter =
-struct
-
-	type source_writer =
-	{
-		sw_buf : Buffer.t;
-		mutable sw_has_content : bool;
-		mutable sw_indent : string;
-		mutable sw_indents : string list;
-	}
-
-	let new_source_writer () =
-		{
-			sw_buf = Buffer.create 0;
-			sw_has_content = false;
-			sw_indent = "";
-			sw_indents = [];
-		}
-
-	let add_writer w_write w_read = Buffer.add_buffer w_read.sw_buf w_write.sw_buf
-
-	let contents w = Buffer.contents w.sw_buf
-
-	let len w = Buffer.length w.sw_buf
-
-	let write w x =
-		(if not w.sw_has_content then begin w.sw_has_content <- true; Buffer.add_string w.sw_buf w.sw_indent; Buffer.add_string w.sw_buf x; end else Buffer.add_string w.sw_buf x);
-		let len = (String.length x)-1 in
-		if len >= 0 && String.get x len = '\n' then begin w.sw_has_content <- false end else w.sw_has_content <- true
-
-	let push_indent w = w.sw_indents <- "\t"::w.sw_indents; w.sw_indent <- String.concat "" w.sw_indents
-
-	let pop_indent w =
-		match w.sw_indents with
-			| h::tail -> w.sw_indents <- tail; w.sw_indent <- String.concat "" w.sw_indents
-			| [] -> w.sw_indent <- "/*?*/"
-
-	let newline w = write w "\n"
-
-	let begin_block w = (if w.sw_has_content then newline w); write w "{"; push_indent w; newline w
-
-	let end_block w = pop_indent w; (if w.sw_has_content then newline w); write w "}"; newline w
-
-	let print w =
-		(if not w.sw_has_content then begin w.sw_has_content <- true; Buffer.add_string w.sw_buf w.sw_indent end);
-		bprintf w.sw_buf;
-
-end;;
-
-(* rule_dispatcher's priority *)
-type priority =
-	| PFirst
-	| PLast
-	| PZero
-	| PCustom of float
-
-exception DuplicateName of string
-exception NoRulesApplied
-
-let indent = ref []
-
-(* the rule dispatcher is the primary way to deal with distributed "plugins" *)
-(* we will define rules that will form a distributed / extensible match system *)
-class ['tp, 'ret] rule_dispatcher name =
-	object(self)
-	val tbl = Hashtbl.create 16
-	val mutable keys = []
-	val names = Hashtbl.create 16
-
-	method add (name : string) (* name helps debugging *) (priority : priority) (rule : 'tp->'ret option) =
-		let p = match priority with
-			| PFirst -> infinity
-			| PLast -> neg_infinity
-			| PZero -> 0.0
-			| PCustom i -> i
-		in
-
-		let q = if not( Hashtbl.mem tbl p ) then begin
-			let q = Stack.create() in
-			Hashtbl.add tbl p q;
-			keys <- p :: keys;
-			keys <- List.sort (fun x y -> - (compare x y)) keys;
-			q
-		end else Hashtbl.find tbl p in
-		(if Hashtbl.mem names name then raise (DuplicateName(name)));
-		Hashtbl.add names name q;
-
-		Stack.push (name, rule) q
-
-	method describe =
-		Hashtbl.iter (fun s _ -> (trace s)) names;
-
-	method run_f tp = get (self#run tp)
-
-	method run_from (priority:float) (tp:'tp) : 'ret option =
-		let ok = ref false in
-		let ret = ref None in
-		indent := "\t" :: !indent;
-
-		(try begin
-			List.iter (fun key ->
-				if key < priority then begin
-					let q = Hashtbl.find tbl key in
-					Stack.iter (fun (n, rule) ->
-						let t = if !debug_mode then Timer.timer [("rule dispatcher rule: " ^ n)] else fun () -> () in
-						let r = rule(tp) in
-						t();
-						if is_some r then begin ret := r; raise Exit end
-					) q
-				end
-			) keys
-
-		end with Exit -> ok := true);
-
-		(match !indent with
-			| [] -> ()
-			| h::t -> indent := t);
-
-		(if not (!ok) then raise NoRulesApplied);
-		!ret
-
-	method run (tp:'tp) : 'ret option =
-		self#run_from infinity tp
-
-end;;
-
-(* this is a special case where tp = tret and you stack their output as the next's input *)
-class ['tp] rule_map_dispatcher name = object(self)
-	val tbl = Hashtbl.create 16
-	val mutable keys = []
-	val names = Hashtbl.create 16
-
-	method add (name : string) (* name helps debugging *) (priority : priority) (rule : 'tp->'tp) =
-		let p = match priority with
-			| PFirst -> infinity
-			| PLast -> neg_infinity
-			| PZero -> 0.0
-			| PCustom i -> i
-		in
-		let q = if not (Hashtbl.mem tbl p) then begin
-			let q = Stack.create() in
-			Hashtbl.add tbl p q;
-			keys <- p :: keys;
-			keys <- List.sort (fun x y -> - (compare x y)) keys;
-			q
-		end else Hashtbl.find tbl p in
-		if Hashtbl.mem names name then raise (DuplicateName name);
-		Hashtbl.add names name q;
-
-		Stack.push (name, rule) q
-
-	method describe =
-		Hashtbl.iter (fun s _ -> (trace s)) names;
-
-	method run (tp:'tp) : 'tp =
-		self#run_from infinity tp
-
-	method run_from (priority:float) (tp:'tp) : 'tp =
-		let cur = ref tp in
-		List.iter (fun key ->
-			if key < priority then begin
-				let q = Hashtbl.find tbl key in
-				Stack.iter (fun (n, rule) ->
-					trace ("running rule " ^ n);
-					let t = if !debug_mode then Timer.timer [("rule map dispatcher rule: " ^ n)] else fun () -> () in
-					cur := rule !cur;
-					t();
-				) q
-			end
-		) keys;
-		!cur
-end;;
-
-
-type generator_ctx =
-{
-	(* these are the basic context fields. If another target is using this context, *)
-	(* this is all you need to care about *)
-	gcon : Common.context;
-
-	gentry_point : (string * tclass * texpr) option;
-
-	gclasses : gen_classes;
-
-	gtools : gen_tools;
-
-	gwarning : Warning.warning -> string -> pos -> unit;
-
-	(*
-		module filters run before module filters and they should generate valid haxe syntax as a result.
-		Module filters shouldn't go through the expressions as it adds an unnecessary burden to the GC,
-		and it can all be done in a single step with gexpr_filters and proper priority selection.
-
-		As a convention, Module filters should end their name with Modf, so they aren't mistaken with expression filters
-	*)
-	gmodule_filters : (module_type) rule_map_dispatcher;
-
-	(*
-		expression filters are the most common filters to be applied.
-		They should also generate only valid haxe expressions, so e.g. calls to non-existant methods
-		should be avoided, although there are some ways around them (like gspecial_methods)
-	*)
-	gexpr_filters : (texpr) rule_map_dispatcher;
-	(*
-		syntax filters are also expression filters but they no longer require
-		that the resulting expressions be valid haxe expressions.
-		They then have no guarantee that either the input expressions or the output one follow the same
-		rules as normal haxe code.
-	*)
-	gsyntax_filters : (texpr) rule_map_dispatcher;
-
-	(* these are more advanced features, but they would require a rewrite of targets *)
-	(* they are just helpers to ditribute functions like "follow" or "type to string" *)
-	(* so adding a module will already take care of correctly following a certain type of *)
-	(* variable, for example *)
-
-	(* follows the type through typedefs, lazy typing, etc. *)
-	(* it's the place to put specific rules to handle typedefs, like *)
-	(* other basic types like UInt *)
-	gfollow : (t, t) rule_dispatcher;
-
-	gtypes : (path, module_type) Hashtbl.t;
-	mutable gtypes_list : module_type list;
-	mutable gmodules : Type.module_def list;
-
-	(* cast detection helpers / settings *)
-	(* this is a cache for all field access types *)
-	greal_field_types : (path * string, (tclass_field (* does the cf exist *) * t (*cf's type in relation to current class type params *) * t * tclass (* declared class *) ) option) Hashtbl.t;
-	(* this function allows any code to handle casts as if it were inside the cast_detect module *)
-	mutable ghandle_cast : t->t->texpr->texpr;
-	(* when an unsafe cast is made, we can warn the user *)
-	mutable gon_unsafe_cast : t->t->pos->unit;
-	(* does this type needs to be boxed? Normally always false, unless special type handling must be made *)
-	mutable gneeds_box : t->bool;
-	(* does this 'special type' needs cast to this other type? *)
-	(* this is here so we can implement custom behavior for "opaque" typedefs *)
-	mutable gspecial_needs_cast : t->t->bool;
-	(* sometimes we may want to support unrelated conversions on cast detection *)
-	(* for example, haxe.lang.Null<T> -> T on C# *)
-	(* every time an unrelated conversion is found, each to/from path is searched on this hashtbl *)
-	(* if found, the function will be executed with from_type, to_type. If returns true, it means that *)
-	(* it is a supported conversion, and the unsafe cast routine changes to a simple cast *)
-	gsupported_conversions : (path, t->t->bool) Hashtbl.t;
-
-	(* API for filters *)
-	(* add type can be called at any time, and will add a new module_def that may or may not be filtered *)
-	(* module_type -> should_filter *)
-	mutable gadd_type : module_type -> bool -> unit;
-	(* during expr filters, add_to_module will be available so module_types can be added to current module_def. we must pass the priority argument so the filters can be resumed	*)
-	mutable gadd_to_module : module_type -> float -> unit;
-	(* during expr filters, shows the current class path *)
-	mutable gcurrent_path : path;
-	(* current class *)
-	mutable gcurrent_class : tclass option;
-	(* current class field, if any *)
-	mutable gcurrent_classfield : tclass_field option;
-
-	(* events *)
-	(* after module filters ended *)
-	mutable gafter_mod_filters_ended : (unit -> unit) list;
-	(* after expression filters ended *)
-	mutable gafter_expr_filters_ended : (unit -> unit) list;
-	(* after all filters are run *)
-	mutable gafter_filters_ended : (unit -> unit) list;
-
-	mutable gbase_class_fields : (string, tclass_field) PMap.t;
-
-	(* real type is the type as it is read by the target. *)
-	(* This function is here because most targets don't have *)
-	(* a 1:1 translation between haxe types and its native types *)
-	(* But types aren't changed to this representation as we might lose *)
-	(* some valuable type information in the process *)
-	mutable greal_type : t -> t;
-	(*
-		the same as greal_type but for type parameters.
-	*)
-	mutable greal_type_param : module_type -> tparams -> tparams;
-	(*
-		is the type a value type?
-		This may be used in some optimizations where reference types and value types
-		are handled differently. At first the default is very good to use, and if tweaks are needed,
-		it's best to be done by adding @:struct meta to the value types
-	*
-	mutable gis_value_type : t -> bool;*)
-
-	(* misc configuration *)
-	(*
-		Should the target allow type parameter dynamic conversion,
-		or should we add a cast to those cases as well?
-	*)
-	mutable gallow_tp_dynamic_conversion : bool;
-
-	(* internal apis *)
-	(* param_func_call : used by RealTypeParams and CastDetection *)
-	mutable gparam_func_call : texpr->texpr->tparams->texpr list->texpr;
-	(* does it already have a type parameter cast handler? This is used by CastDetect to know if it should handle type parameter casts *)
-	mutable ghas_tparam_cast_handler : bool;
-	(* type parameter casts - special cases *)
-	(* function cast_from, cast_to -> texpr *)
-	gtparam_cast : (path, (texpr->t->texpr)) Hashtbl.t;
-
-	(*
-		special vars are used for adding special behavior to
-	*)
-	gspecial_vars : (string, bool) Hashtbl.t;
-}
-
-and gen_classes =
-{
-	cl_reflect : tclass;
-	cl_type : tclass;
-	cl_dyn : tclass;
-
-	mutable nativearray_len : texpr -> pos -> texpr;
-	mutable nativearray_type : Type.t -> Type.t;
-	mutable nativearray : Type.t -> Type.t;
-}
-
-(* add here all reflection transformation additions *)
-and gen_tools =
-{
-	(* Reflect.fields(). The bool is if we are iterating in a read-only manner. If it is read-only we might not need to allocate a new array *)
-	r_fields : bool->texpr->texpr;
-	(* (first argument = return type. should be void in most cases) Reflect.setField(obj, field, val) *)
-	r_set_field : t->texpr->texpr->texpr->texpr;
-	(* Reflect.field. bool indicates if is safe (no error throwing) or unsafe; t is the expected return type true = safe *)
-	r_field : bool->t->texpr->texpr->texpr;
-
-	(*
-		return an expression that creates an unitialized instance of a class, used for the generic cast helper method.
-	*)
-	mutable r_create_empty : tclass->tparams->pos->texpr;
-}
-
-(**
-	Function that receives a desired name and makes it "internal", doing the best to ensure that it will not be called from outside.
-	To avoid name clashes between internal names, user must specify two strings: a "namespace" and the name itself
-*)
-let mk_internal_name ns name = Printf.sprintf "__%s_%s" ns name
-
-let mk_temp, reset_temps =
-	let tmp_count = ref 0 in
-	(fun name t ->
-		incr tmp_count;
-		let name = mk_internal_name "temp" (name ^ (string_of_int !tmp_count)) in
-		alloc_var name t
-	),
-	(fun () -> tmp_count := 0)
-
-let new_ctx con =
-	let types = Hashtbl.create (List.length con.types) in
-	List.iter (fun mt ->
-		match mt with
-			| TClassDecl cl -> Hashtbl.add types cl.cl_path mt
-			| TEnumDecl e -> Hashtbl.add types e.e_path mt
-			| TTypeDecl t -> Hashtbl.add types t.t_path mt
-			| TAbstractDecl a ->
-				(* There are some cases where both an abstract and a class
-				   have the same name (e.g. java.lang.Double/Integer/etc)
-				   in this case we generally want the class to have priority *)
-				if not (Hashtbl.mem types a.a_path) then
-					Hashtbl.add types a.a_path mt
-	) con.types;
-
-	let get_type path =
-		List.find (fun md -> (t_path md) = path) con.types
-	in
-
-	let cl_dyn = match get_type  ([], "Dynamic") with
-		| TClassDecl c -> c
-		| TAbstractDecl a ->
-				mk_class a.a_module ([], "Dynamic") a.a_pos null_pos
-		| _ -> die "" __LOC__
-	in
-
-	let rec gen = {
-		gcon = con;
-		gwarning = (fun w msg p ->
-			let options = Option.map_default (fun c -> Warning.from_meta c.cl_meta) [] gen.gcurrent_class in
-			let options = options @ Option.map_default (fun cf -> Warning.from_meta cf.cf_meta) [] gen.gcurrent_classfield in
-			con.warning w options msg p
-		);
-		gentry_point = get_entry_point con;
-		gclasses = {
-			cl_reflect = get_cl (get_type ([], "Reflect"));
-			cl_type = get_cl (get_type ([], "Type"));
-			cl_dyn = cl_dyn;
-
-			nativearray = (fun _ -> die "" __LOC__);
-			nativearray_type = (fun _ -> die "" __LOC__);
-			nativearray_len = (fun _ -> die "" __LOC__);
-		};
-		gtools = {
-			r_fields = (fun is_used_only_by_iteration expr ->
-				let fieldcall = mk_static_field_access_infer gen.gclasses.cl_reflect "fields" expr.epos [] in
-				{ eexpr = TCall(fieldcall, [expr]); etype = gen.gcon.basic.tarray gen.gcon.basic.tstring; epos = expr.epos }
-			);
-			(* Reflect.setField(obj, field, val). t by now is ignored. FIXME : fix this implementation *)
-			r_set_field = (fun t obj field v ->
-				let fieldcall = mk_static_field_access_infer gen.gclasses.cl_reflect "setField" v.epos [] in
-				{ eexpr = TCall(fieldcall, [obj; field; v]); etype = t_dynamic; epos = v.epos }
-			);
-			(* Reflect.field. bool indicates if is safe (no error throwing) or unsafe. true = safe *)
-			r_field = (fun is_safe t obj field ->
-				let fieldcall = mk_static_field_access_infer gen.gclasses.cl_reflect "field" obj.epos [] in
-				(* FIXME: should we see if needs to cast? *)
-				mk_cast t { eexpr = TCall(fieldcall, [obj; field]); etype = t_dynamic; epos = obj.epos }
-			);
-
-			r_create_empty = (fun _ _ pos -> gen.gcon.error "r_create_empty implementation is not provided" pos; die "" __LOC__);
-		};
-		gexpr_filters = new rule_map_dispatcher "gexpr_filters";
-		gmodule_filters = new rule_map_dispatcher "gmodule_filters";
-		gsyntax_filters = new rule_map_dispatcher "gsyntax_filters";
-		gfollow = new rule_dispatcher "gfollow";
-		gtypes = types;
-		gtypes_list = con.types;
-		gmodules = con.modules;
-
-		greal_field_types = Hashtbl.create 0;
-		ghandle_cast = (fun to_t from_t e -> mk_cast to_t e);
-		gon_unsafe_cast = (fun t t2 pos -> (gen.gwarning WGenerator ("Type " ^ (debug_type t2) ^ " is being cast to the unrelated type " ^ (s_type (print_context()) t)) pos));
-		gneeds_box = (fun t -> false);
-		gspecial_needs_cast = (fun to_t from_t -> false);
-		gsupported_conversions = Hashtbl.create 0;
-
-		gadd_type = (fun md should_filter ->
-			if should_filter then begin
-				gen.gtypes_list <- md :: gen.gtypes_list;
-				gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_statics = None; m_extra = module_extra "" "" 0. MFake [] } :: gen.gmodules;
-				Hashtbl.add gen.gtypes (t_path md) md;
-			end else gen.gafter_filters_ended <- (fun () ->
-				gen.gtypes_list <- md :: gen.gtypes_list;
-				gen.gmodules <- { m_id = alloc_mid(); m_path = (t_path md); m_types = [md]; m_statics = None; m_extra = module_extra "" "" 0. MFake [] } :: gen.gmodules;
-				Hashtbl.add gen.gtypes (t_path md) md;
-			) :: gen.gafter_filters_ended;
-		);
-		gadd_to_module = (fun md pr -> failwith "module added outside expr filters");
-		gcurrent_path = ([],"");
-		gcurrent_class = None;
-		gcurrent_classfield = None;
-
-		gafter_mod_filters_ended = [];
-		gafter_expr_filters_ended = [];
-		gafter_filters_ended = [];
-
-		gbase_class_fields = PMap.empty;
-
-		greal_type = (fun t -> t);
-		greal_type_param = (fun _ t -> t);
-
-		gallow_tp_dynamic_conversion = false;
-
-		(* as a default, ignore the params *)
-		gparam_func_call = (fun ecall efield params elist -> { ecall with eexpr = TCall(efield, elist) });
-		ghas_tparam_cast_handler = false;
-		gtparam_cast = Hashtbl.create 0;
-
-		gspecial_vars = Hashtbl.create 0;
-	} in
-	gen
-
-let init_ctx gen =
-	(* ultimately add a follow once handler as the last follow handler *)
-	let follow_f = gen.gfollow#run in
-	let follow t =
-		match t with
-		| TMono r ->
-			(match r.tm_type with
-			| Some t -> follow_f t
-			| _ -> Some t)
-		| TLazy f ->
-			follow_f (lazy_type f)
-		| TType (t,tl) ->
-			follow_f (apply_typedef t tl)
-		| TAbstract({a_path = [],"Null"},[t]) ->
-			follow_f t
-		| _ -> Some t
-	in
-	gen.gfollow#add "final" PLast follow
-
-let run_follow gen = gen.gfollow#run_f
-
-let reorder_modules gen =
-	let modules = Hashtbl.create 20 in
-	List.iter (fun md ->
-		Hashtbl.add modules ( (t_infos md).mt_module ).m_path md
-	) gen.gtypes_list;
-
-	gen.gmodules <- [];
-	let processed = Hashtbl.create 20 in
-	Hashtbl.iter (fun md_path md ->
-		if not (Hashtbl.mem processed md_path) then begin
-			Hashtbl.add processed md_path true;
-			gen.gmodules <- { m_id = alloc_mid(); m_path = md_path; m_types = List.rev ( Hashtbl.find_all modules md_path ); m_statics = None; m_extra = (t_infos md).mt_module.m_extra } :: gen.gmodules
-		end
-	) modules
-
-let run_filters_from gen t filters =
-	match t with
-	| TClassDecl c when not (FiltersCommon.is_removable_class c) ->
-		trace (snd c.cl_path);
-		gen.gcurrent_path <- c.cl_path;
-		gen.gcurrent_class <- Some(c);
-
-		gen.gcurrent_classfield <- None;
-		let rec process_field f =
-			reset_temps();
-			gen.gcurrent_classfield <- Some(f);
-
-			trace f.cf_name;
-			(match f.cf_expr with
-			| None -> ()
-			| Some e ->
-				f.cf_expr <- Some (List.fold_left (fun e f -> f e) e filters));
-			List.iter process_field f.cf_overloads;
-		in
-		List.iter process_field c.cl_ordered_fields;
-		List.iter process_field c.cl_ordered_statics;
-
-		(match c.cl_constructor with
-		| None -> ()
-		| Some f -> process_field f);
-		gen.gcurrent_classfield <- None;
-		(match c.cl_init with
-		| None -> ()
-		| Some e ->
-			c.cl_init <- Some (List.fold_left (fun e f -> f e) e filters));
-	| TClassDecl _ | TEnumDecl _ | TTypeDecl _ | TAbstractDecl _ ->
-		()
-
-let run_filters gen =
-	let last_error = gen.gcon.located_error in
-	let has_errors = ref false in
-	gen.gcon.located_error <- (fun ?(depth=0) msg -> has_errors := true; last_error ~depth msg);
-	(* first of all, we have to make sure that the filters won't trigger a major Gc collection *)
-	let t = Timer.timer ["gencommon_filters"] in
-	(if Common.defined gen.gcon Define.GencommonDebug then debug_mode := true else debug_mode := false);
-	let run_filters (filter : texpr rule_map_dispatcher) =
-		let rec loop acc mds =
-			match mds with
-				| [] -> acc
-				| md :: tl ->
-					let filters = [ filter#run ] in
-					let added_types = ref [] in
-					gen.gadd_to_module <- (fun md_type priority ->
-						gen.gtypes_list <- md_type :: gen.gtypes_list;
-						added_types := (md_type, priority) :: !added_types
-					);
-
-					run_filters_from gen md filters;
-
-					let added_types = List.map (fun (t,p) ->
-						run_filters_from gen t [ fun e -> filter#run_from p e ];
-						if Hashtbl.mem gen.gtypes (t_path t) then begin
-							let rec loop i =
-								let p = t_path t in
-								let new_p = (fst p, snd p ^ "_" ^ (string_of_int i)) in
-								if Hashtbl.mem gen.gtypes new_p then
-									loop (i+1)
-								else
-									match t with
-										| TClassDecl cl -> cl.cl_path <- new_p
-										| TEnumDecl e -> e.e_path <- new_p
-										| TTypeDecl _ | TAbstractDecl _ -> ()
-							in
-							loop 0
-						end;
-						Hashtbl.add gen.gtypes (t_path t) t;
-						t
-					) !added_types in
-
-					loop (added_types @ (md :: acc)) tl
-		in
-		List.rev (loop [] gen.gtypes_list)
-	in
-
-	let run_mod_filter (filter : module_type rule_map_dispatcher) =
-		let last_add_to_module = gen.gadd_to_module in
-		let added_types = ref [] in
-		gen.gadd_to_module <- (fun md_type priority ->
-			Hashtbl.add gen.gtypes (t_path md_type) md_type;
-			added_types := (md_type, priority) :: !added_types
-		);
-
-		let rec loop processed not_processed =
-			match not_processed with
-				| hd :: tl ->
-					(match hd with
-						| TClassDecl c ->
-							gen.gcurrent_class <- Some c
-						| _ ->
-							gen.gcurrent_class <- None);
-					let new_hd = filter#run hd in
-
-					let added_types_new = !added_types in
-					added_types := [];
-					let added_types = List.map (fun (t,p) -> filter#run_from p t) added_types_new in
-
-					loop ( added_types @ (new_hd :: processed) ) tl
-				| [] ->
-					processed
-		in
-
-		let filtered = loop [] gen.gtypes_list in
-		gen.gadd_to_module <- last_add_to_module;
-		gen.gtypes_list <- List.rev (filtered)
-	in
-
-	run_mod_filter gen.gmodule_filters;
-	List.iter (fun fn -> fn()) gen.gafter_mod_filters_ended;
-
-	let last_add_to_module = gen.gadd_to_module in
-	gen.gtypes_list <- run_filters gen.gexpr_filters;
-	gen.gadd_to_module <- last_add_to_module;
-
-	List.iter (fun fn -> fn()) gen.gafter_expr_filters_ended;
-	gen.gtypes_list <- run_filters gen.gsyntax_filters;
-	List.iter (fun fn -> fn()) gen.gafter_filters_ended;
-
-	reorder_modules gen;
-	t();
-	if !has_errors then abort "Compilation aborted with errors" null_pos
-
-(* ******************************************* *)
-(* basic generation module that source code compilation implementations can use *)
-(* ******************************************* *)
-
-let write_file gen w source_dir path extension out_files =
-	let t = timer ["write";"file"] in
-	let s_path = source_dir	^ "/" ^ (snd path) ^ "." ^ (extension) in
-	(* create the folders if they don't exist *)
-	Path.mkdir_from_path s_path;
-
-	let contents = SourceWriter.contents w in
-	let should_write = if not (Common.defined gen.gcon Define.ReplaceFiles) && Sys.file_exists s_path then begin
-		let in_file = open_in s_path in
-		let old_contents = Std.input_all in_file in
-		close_in in_file;
-		contents <> old_contents
-	end else true in
-
-	if should_write then begin
-		let f = open_out_bin s_path in
-		output_string f contents;
-		close_out f
-	end;
-
-	out_files := (gen.gcon.file_keys#get s_path) :: !out_files;
-
-	t()
-
-
-let clean_files gen path excludes verbose =
-	let rec iter_files pack dir path = try
-		let file = Unix.readdir dir in
-
-		if file <> "." && file <> ".." then begin
-			let filepath = path ^ "/" ^ file in
-			if (Unix.stat filepath).st_kind = S_DIR then
-				let pack = pack @ [file] in
-				iter_files (pack) (Unix.opendir filepath) filepath;
-				try Unix.rmdir filepath with Unix.Unix_error (ENOTEMPTY,_,_) -> ();
-			else if not (String.ends_with filepath ".meta") && not (List.mem (gen.gcon.file_keys#get filepath) excludes) then begin
-				if verbose then print_endline ("Removing " ^ filepath);
-			 	Sys.remove filepath
-			end
-		end;
-
-		iter_files pack dir path
-	with | End_of_file | Unix.Unix_error _ ->
-		Unix.closedir dir
-	in
-	iter_files [] (Unix.opendir path) path
-
-
-let dump_descriptor gen name path_s module_s =
-	let w = SourceWriter.new_source_writer () in
-	(* dump called path *)
-	SourceWriter.write w (Sys.getcwd());
-	SourceWriter.newline w;
-	(* dump all defines. deprecated *)
-	SourceWriter.write w "begin defines";
-	SourceWriter.newline w;
-	PMap.iter (fun name _ ->
-		SourceWriter.write w name;
-		SourceWriter.newline w
-	) gen.gcon.defines.Define.values;
-	SourceWriter.write w "end defines";
-	SourceWriter.newline w;
-	(* dump all defines with their values; keeping the old defines for compatibility *)
-	SourceWriter.write w "begin defines_data";
-	SourceWriter.newline w;
-	PMap.iter (fun name v ->
-		SourceWriter.write w name;
-		SourceWriter.write w "=";
-		SourceWriter.write w v;
-		SourceWriter.newline w
-	) gen.gcon.defines.Define.values;
-	SourceWriter.write w "end defines_data";
-	SourceWriter.newline w;
-	(* dump all generated types *)
-	SourceWriter.write w "begin modules";
-	SourceWriter.newline w;
-	let main_paths = Hashtbl.create 0 in
-	List.iter (fun md_def ->
-		SourceWriter.write w "M ";
-		SourceWriter.write w (path_s (path_of_md_def md_def));
-		SourceWriter.newline w;
-		List.iter (fun m ->
-			match m with
-				| TClassDecl cl when not (has_class_flag cl CExtern) ->
-					SourceWriter.write w "C ";
-					let s = module_s m in
-					Hashtbl.add main_paths cl.cl_path s;
-					SourceWriter.write w (s);
-					SourceWriter.newline w
-				| TEnumDecl e when not e.e_extern ->
-					SourceWriter.write w "E ";
-					SourceWriter.write w (module_s m);
-					SourceWriter.newline w
-				| _ -> () (* still no typedef or abstract is generated *)
-		) md_def.m_types
-	) gen.gmodules;
-	SourceWriter.write w "end modules";
-	SourceWriter.newline w;
-	(* dump all resources *)
-	(match gen.gentry_point with
-	| Some (_,cl,_) ->
-		SourceWriter.write w "begin main";
-		SourceWriter.newline w;
-		let path = cl.cl_path in
-		(try
-			SourceWriter.write w (Hashtbl.find main_paths path)
-		with Not_found ->
-			SourceWriter.write w (path_s path));
-		SourceWriter.newline w;
-		SourceWriter.write w "end main";
-		SourceWriter.newline w
-	| _ -> ());
-	SourceWriter.write w "begin resources";
-	SourceWriter.newline w;
-	Hashtbl.iter (fun name _ ->
-		SourceWriter.write w name;
-		SourceWriter.newline w
-	) gen.gcon.resources;
-	SourceWriter.write w "end resources";
-	SourceWriter.newline w;
-	SourceWriter.write w "begin libs";
-	SourceWriter.newline w;
-	let path file ext =
-		if Sys.file_exists file then
-			file
-		else try Common.find_file gen.gcon file with
-			| Not_found -> try Common.find_file gen.gcon (file ^ ext) with
-			| Not_found ->
-				file
-	in
-	if Common.platform gen.gcon Java then
-		List.iter (fun java_lib ->
-			if not (java_lib#has_flag NativeLibraries.FlagIsStd) && not (java_lib#has_flag NativeLibraries.FlagIsExtern) then begin
-				SourceWriter.write w (path java_lib#get_file_path ".jar");
-				SourceWriter.newline w;
-			end
-		) gen.gcon.native_libs.java_libs
-	else if Common.platform gen.gcon Cs then
-		List.iter (fun net_lib ->
-			if not (net_lib#has_flag NativeLibraries.FlagIsStd) && not (net_lib#has_flag NativeLibraries.FlagIsExtern) then begin
-				SourceWriter.write w (path net_lib#get_name ".dll");
-				SourceWriter.newline w;
-			end
-		) gen.gcon.native_libs.net_libs;
-	SourceWriter.write w "end libs";
-	SourceWriter.newline w;
-	let args = gen.gcon.c_args in
-	if args <> [] then begin
-		SourceWriter.write w "begin opts";
-		SourceWriter.newline w;
-		List.iter (fun opt -> SourceWriter.write w opt; SourceWriter.newline w) (List.rev args);
-		SourceWriter.write w "end opts";
-		SourceWriter.newline w;
-	end;
-
-	let contents = SourceWriter.contents w in
-	let f = open_out (gen.gcon.file ^ "/" ^ name) in
-	output_string f contents;
-	close_out f
-
-(*
-	various helper functions
-*)
-
-let mk_paren e =
-	match e.eexpr with | TParenthesis _ -> e | _ -> { e with eexpr=TParenthesis(e) }
-
-(* private *)
-
-let get_real_fun gen t =
-	match follow t with
-	| TFun(args,t) -> TFun(List.map (fun (n,o,t) -> n,o,gen.greal_type t) args, gen.greal_type t)
-	| _ -> t
-
-let mk_nativearray_decl gen t el pos =
-	mk (TCall (mk (TIdent "__array__") t_dynamic pos, el)) (gen.gclasses.nativearray t) pos
-
-
-let get_boxed gen t =
-	let get path =
-		try type_of_module_type (Hashtbl.find gen.gtypes path)
-		with Not_found -> t
-	in
-	match follow t with
-	| TAbstract({ a_path = ([],"Bool") }, []) ->
-		get (["java";"lang"], "Boolean")
-	| TAbstract({ a_path = ([],"Float") }, []) ->
-		get (["java";"lang"], "Double")
-	| TAbstract({ a_path = ([],"Int") }, []) ->
-		get (["java";"lang"], "Integer")
-	| TAbstract({ a_path = (["java"],"Int8") }, []) ->
-		get (["java";"lang"], "Byte")
-	| TAbstract({ a_path = (["java"],"Int16") }, []) ->
-		get (["java";"lang"], "Short")
-	| TAbstract({ a_path = (["java"],"Char16") }, []) ->
-		get (["java";"lang"], "Character")
-	| TAbstract({ a_path = ([],"Single") }, []) ->
-		get (["java";"lang"], "Float")
-	| TAbstract({ a_path = (["java"],"Int64") }, [])
-	| TAbstract({ a_path = (["haxe"],"Int64") }, []) ->
-		get (["java";"lang"], "Long")
-	| _ -> t
-
-(**
-	Wraps rest arguments into a native array.
-	E.g. transforms params from `callee(param, rest1, rest2, ..., restN)` into
-	`callee(param, untyped __array__(rest1, rest2, ..., restN))`
-*)
-let wrap_rest_args gen callee_type params p =
-	match follow callee_type with
-	| TFun(args, _) ->
-		let rec loop args params =
-			match args, params with
-			(* last argument expects rest parameters *)
-			| [(_,_,t)], params when ExtType.is_rest (follow t) ->
-				(match params with
-				(* In case of `...rest` just use `rest` *)
-				| [{ eexpr = TUnop(Spread,Prefix,e) }] -> [e]
-				(* In other cases: `untyped __array__(param1, param2, ...)` *)
-				| _ ->
-					match Abstract.follow_with_abstracts t with
-					| TInst ({ cl_path = _,"NativeArray" }, [t1]) ->
-						let t1 = if Common.defined gen.gcon Define.EraseGenerics then t_dynamic else get_boxed gen t1 in
-						[mk_nativearray_decl gen t1 params (punion_el p params)]
-					| _ ->
-						die ~p "Unexpected rest arguments type" __LOC__
-				)
-			| a :: args, e :: params ->
-				e :: loop args params
-			| [], params ->
-				params
-			| _ :: _, [] ->
-				[]
-		in
-		loop args params
-	| _ -> params
-
-let ensure_local com block name e =
-	match e.eexpr with
-	| TLocal _ -> e
-	| _ ->
-		let v = mk_temp name e.etype in
-		block := (mk (TVar (v, Some e)) com.basic.tvoid e.epos) :: !block;
-		mk_local v e.epos
-
-let follow_module follow_func md = match md with
-	| TClassDecl _
-	| TEnumDecl _
-	| TAbstractDecl _ -> md
-	| TTypeDecl tdecl -> match (follow_func (TType(tdecl, extract_param_types tdecl.t_params))) with
-		| TInst(cl,_) -> TClassDecl cl
-		| TEnum(e,_) -> TEnumDecl e
-		| TType(t,_) -> TTypeDecl t
-		| TAbstract(a,_) -> TAbstractDecl a
-		| _ -> die "" __LOC__
-
-(*
-	hxgen means if the type was generated by haxe. If a type was generated by haxe, it means
-	it will contain special constructs for speedy reflection, for example
-
-	@see SetHXGen module
- *)
-let rec is_hxgen md =
-	match md with
-		| TClassDecl cl -> Meta.has Meta.HxGen cl.cl_meta
-		| TEnumDecl e -> Meta.has Meta.HxGen e.e_meta
-		| TTypeDecl t -> Meta.has Meta.HxGen t.t_meta || ( match follow t.t_type with | TInst(cl,_) -> is_hxgen (TClassDecl cl) | TEnum(e,_) -> is_hxgen (TEnumDecl e) | _ -> false )
-		| TAbstractDecl a -> Meta.has Meta.HxGen a.a_meta
-
-let is_hxgen_t t =
-	match t with
-		| TInst (cl, _) -> Meta.has Meta.HxGen cl.cl_meta
-		| TEnum (e, _) -> Meta.has Meta.HxGen e.e_meta
-		| TAbstract (a, _) -> Meta.has Meta.HxGen a.a_meta
-		| TType (t, _) -> Meta.has Meta.HxGen t.t_meta
-		| _ -> false
-
-let mt_to_t_dyn md =
-	match md with
-		| TClassDecl cl -> TInst(cl, List.map (fun _ -> t_dynamic) cl.cl_params)
-		| TEnumDecl e -> TEnum(e, List.map (fun _ -> t_dynamic) e.e_params)
-		| TAbstractDecl a -> TAbstract(a, List.map (fun _ -> t_dynamic) a.a_params)
-		| TTypeDecl t -> TType(t, List.map (fun _ -> t_dynamic) t.t_params)
-
-(* replace open TMonos with TDynamic *)
-let rec replace_mono t =
-	match t with
-	| TMono t ->
-		(match t.tm_type with
-		| None -> Monomorph.bind t t_dynamic
-		| Some _ -> ())
-	| TEnum (_,p) | TInst (_,p) | TType (_,p) | TAbstract (_,p) ->
-		List.iter replace_mono p
-	| TFun (args,ret) ->
-		List.iter (fun (_,_,t) -> replace_mono t) args;
-		replace_mono ret
-	| TAnon _
-	| TDynamic _ -> ()
-	| TLazy f ->
-		replace_mono (lazy_type f)
-
-(* helper *)
-let mk_class_field ?(static = false) name t public pos kind params =
-	let f = mk_field name ~public ~static t pos null_pos in
-	f.cf_meta <- [ Meta.CompilerGenerated, [], null_pos ]; (* annotate that this class field was generated by the compiler *)
-	f.cf_kind <- kind;
-	f.cf_params <- params;
-	f
-
-(* this helper just duplicates the type parameter class, which is assumed that cl is. *)
-(* This is so we can use class parameters on function parameters, without running the risk of name clash *)
-(* between both *)
-let map_param cl =
-	let ret = mk_class cl.cl_module (fst cl.cl_path, snd cl.cl_path ^ "_c") cl.cl_pos null_pos in
-	ret.cl_implements <- cl.cl_implements;
-	ret.cl_kind <- cl.cl_kind;
-	ret
-
-let get_cl_t t =
-	match follow t with | TInst (cl,_) -> cl | _ -> die "" __LOC__
-
-let mk_class m path pos =
-	let cl = Type.mk_class m path pos null_pos in
-	cl.cl_meta <- [ Meta.CompilerGenerated, [], null_pos ];
-	cl
-
-type tfield_access =
-	| FClassField of tclass * tparams * tclass (* declared class *) * tclass_field * bool (* is static? *) * t (* the actual cf type, in relation to the class type params *) * t (* declared type *)
-	| FEnumField of tenum * tenum_field * bool (* is parameterized enum ? *)
-	| FAnonField of tclass_field
-	| FDynamicField of t
-	| FNotFound
-
-let is_var f = match f.cf_kind with | Var _ -> true | _ -> false
-
-let find_first_declared_field gen orig_cl ?get_vmtype ?exact_field field =
-	let get_vmtype = match get_vmtype with None -> (fun t -> t) | Some f -> f in
-	let chosen = ref None in
-	let is_overload = ref false in
-	let rec loop_cl depth c tl tlch =
-		(try
-			let ret = PMap.find field c.cl_fields in
-			if has_class_field_flag ret CfOverload then is_overload := true;
-			match !chosen, exact_field with
-			| Some(d,f,_,_,_), _ when depth <= d || (is_var ret && not (is_var f)) -> ()
-			| _, None ->
-				chosen := Some(depth,ret,c,tl,tlch)
-			| _, Some f2 ->
-				List.iter (fun f ->
-					let declared_t = apply_params c.cl_params tl f.cf_type in
-					if same_overload_args ~get_vmtype declared_t f2.cf_type f f2 then
-						chosen := Some(depth,f,c,tl,tlch)
-				) (ret :: ret.cf_overloads)
-		with | Not_found -> ());
-		(match c.cl_super with
-		| Some (sup,stl) ->
-			let tl = List.map (apply_params c.cl_params tl) stl in
-			let stl = gen.greal_type_param (TClassDecl sup) stl in
-			let tlch = List.map (apply_params c.cl_params tlch) stl in
-			loop_cl (depth+1) sup tl tlch
-		| None -> ());
-		if (has_class_flag c CInterface) then
-			List.iter (fun (sup,stl) ->
-				let tl = List.map (apply_params c.cl_params tl) stl in
-				let stl = gen.greal_type_param (TClassDecl sup) stl in
-				let tlch = List.map (apply_params c.cl_params tlch) stl in
-				loop_cl (depth+1) sup tl tlch
-			) c.cl_implements
-	in
-	loop_cl 0 orig_cl (extract_param_types orig_cl.cl_params) (extract_param_types orig_cl.cl_params);
-	match !chosen with
-	| None ->
-		None
-	| Some(_,f,c,tl,tlch) ->
-		if !is_overload && not (has_class_field_flag f CfOverload) then
-			add_class_field_flag f CfOverload;
-		let declared_t = apply_params c.cl_params tl f.cf_type in
-		let params_t = apply_params c.cl_params tlch f.cf_type in
-		let actual_t = match follow params_t with
-		| TFun(args,ret) -> TFun(List.map (fun (n,o,t) -> (n,o,gen.greal_type t)) args, gen.greal_type ret)
-		| _ -> gen.greal_type params_t in
-		Some(f,actual_t,declared_t,params_t,c,tl,tlch)
-
-let rec field_access gen (t:t) (field:string) : (tfield_access) =
-	(*
-		t can be either an haxe-type as a real-type;
-		'follow' should be applied here since we can generalize that a TType will be accessible as its
-		underlying type.
-	*)
-
-	(* let pointers to values be accessed as the underlying values *)
-	let t = match gen.greal_type t with
-		| TAbstract({ a_path = ["cs"],"Pointer" },[t]) ->
-			gen.greal_type t
-		| _ -> t
-	in
-
-	match follow t with
-		| TInst(cl, params) ->
-			let orig_cl = cl in
-			let orig_params = params in
-			let rec not_found cl params =
-				match cl.cl_dynamic with
-					| Some t ->
-						let t = apply_params cl.cl_params params t in
-						FDynamicField t
-					| None ->
-						match cl.cl_super with
-							| None -> FNotFound
-							| Some (super,p) ->  not_found super p
-			in
-
-			let not_found () =
-				try
-					let cf = PMap.find field gen.gbase_class_fields in
-					FClassField (orig_cl, orig_params, gen.gclasses.cl_dyn, cf, false, cf.cf_type, cf.cf_type)
-				with
-					| Not_found -> not_found cl params
-			in
-
-			(* this is a hack for C#'s different generic types with same path *)
-			let hashtbl_field = (String.concat "" (List.map (fun _ -> "]") cl.cl_params)) ^ field in
-			let types = try
-				Hashtbl.find gen.greal_field_types (orig_cl.cl_path, hashtbl_field)
-			with | Not_found ->
-				let ret = find_first_declared_field gen cl field in
-				let ret = match ret with
-					| None -> None
-					| Some(cf,t,dt,_,cl,_,_) -> Some(cf,t,dt,cl)
-				in
-				if ret <> None then Hashtbl.add gen.greal_field_types (orig_cl.cl_path, hashtbl_field) ret;
-				ret
-			in
-			(match types with
-					| None -> not_found()
-					| Some (cf, actual_t, declared_t, declared_cl) ->
-						FClassField(orig_cl, orig_params, declared_cl, cf, false, actual_t, declared_t))
-		| TEnum (en,params) when Meta.has Meta.Class en.e_meta ->
-			(* A field access to an enum could mean accessing field of its generated class (e.g. `index` for switches).
-			   Ideally, we should change all TEnum instances to relevant TInst instances so we never reach this case,
-			   but for now, we're going to find the generated class and make a field access to it instead. *)
-			(try
-				let cl_enum = List.find (function TClassDecl cl when cl.cl_path = en.e_path && Meta.has Meta.Enum cl.cl_meta -> true | _ -> false) gen.gtypes_list in
-				let cl_enum = match cl_enum with TClassDecl cl -> TInst (cl,params) | _ -> die "" __LOC__ in
-				field_access gen cl_enum field
-			with Not_found ->
-				FNotFound)
-		| TAnon anon ->
-			(try match !(anon.a_status) with
-				| Statics cl ->
-					let cf = PMap.find field cl.cl_statics in
-					FClassField(cl, List.map (fun _ -> t_dynamic) cl.cl_params, cl, cf, true, cf.cf_type, cf.cf_type)
-				| EnumStatics e ->
-					let f = PMap.find field e.e_constrs in
-					let is_param = match follow f.ef_type with | TFun _ -> true | _ -> false in
-					FEnumField(e, f, is_param)
-				| _ when PMap.mem field gen.gbase_class_fields ->
-					let cf = PMap.find field gen.gbase_class_fields in
-					FClassField(gen.gclasses.cl_dyn, [t_dynamic], gen.gclasses.cl_dyn, cf, false, cf.cf_type, cf.cf_type)
-				| _ ->
-					FAnonField(PMap.find field anon.a_fields)
-			with | Not_found -> FNotFound)
-		| _ when PMap.mem field gen.gbase_class_fields ->
-			let cf = PMap.find field gen.gbase_class_fields in
-			FClassField(gen.gclasses.cl_dyn, [t_dynamic], gen.gclasses.cl_dyn, cf, false, cf.cf_type, cf.cf_type)
-		| TDynamic t -> FDynamicField (match t with None -> t_dynamic | Some t -> t)
-		| TMono _ -> FDynamicField t_dynamic
-		| _ -> FNotFound
-
-let field_access_esp gen t field = match field with
-	| FStatic(cl,cf) | FInstance(cl,_,cf) when has_class_field_flag cf CfExtern ->
-		let static = match field with
-			| FStatic _ -> true
-			| _ -> false
-		in
-		let p = match follow (run_follow gen t) with
-			| TInst(_,p) -> p
-			| _ -> extract_param_types cl.cl_params
-		in
-		FClassField(cl,p,cl,cf,static,cf.cf_type,cf.cf_type)
-	| _ -> field_access gen t (field_name field)
-
-let mk_field_access gen expr field pos =
-	match field_access gen expr.etype field with
-		| FClassField(c,p,dc,cf,false,at,_) ->
-				{ eexpr = TField(expr, FInstance(dc,p,cf)); etype = apply_params c.cl_params p at; epos = pos }
-		| FClassField(c,p,dc,cf,true,at,_) ->
-				{ eexpr = TField(expr, FStatic(dc,cf)); etype = at; epos = pos }
-		| FAnonField cf ->
-				{ eexpr = TField(expr, FAnon cf); etype = cf.cf_type; epos = pos }
-		| FDynamicField t ->
-				{ eexpr = TField(expr, FDynamic field); etype = t; epos = pos }
-		| FNotFound ->
-				{ eexpr = TField(expr, FDynamic field); etype = t_dynamic; epos = pos }
-		| FEnumField _ -> die "" __LOC__
-
-(* ******************************************* *)
-(* Module dependency resolution *)
-(* ******************************************* *)
-
-type t_dependency =
-	| DAfter of float
-	| DBefore of float
-
-exception ImpossibleDependency of string
-
-let max_dep = 10000.0
-let min_dep = - (10000.0)
-
-let solve_deps name (deps:t_dependency list) =
-	let vmin = min_dep -. 1.0 in
-	let vmax = max_dep +. 1.0 in
-	let rec loop dep vmin vmax =
-		match dep with
-			| [] ->
-				(if vmin >= vmax then raise (ImpossibleDependency name));
-				(vmin +. vmax) /. 2.0
-			| head :: tail ->
-				match head with
-					| DBefore f ->
-						loop tail (max vmin f) vmax
-					| DAfter f ->
-						loop tail vmin (min vmax f)
-	in
-	loop deps vmin vmax
-
-(* type resolution *)
-
-exception TypeNotFound of path
-
-let get_type gen path =
-	try Hashtbl.find gen.gtypes path with | Not_found -> raise (TypeNotFound path)
-
-
-let fun_args l =
-	List.map (fun (v,s) -> (v.v_name, (s <> None), v.v_type)) l
-

+ 0 - 284
src/codegen/gencommon/hardNullableSynf.ml

@@ -1,284 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Common
-open Type
-open Gencommon
-
-(* ******************************************* *)
-(* HardNullableSynf *)
-(* ******************************************* *)
-(*
-	This module will handle Null<T> types for languages that offer a way of dealing with
-	stack-allocated structures or tuples and generics. Essentialy on those targets a Null<T>
-	will be a tuple ( 'a * bool ), where bool is whether the value is null or not.
-
-	At first (configure-time), we will modify the follow function so it can follow correctly nested Null<Null<T>>,
-	and do not follow Null<T> to its underlying type
-
-	Then we will run a syntax filter, which will look for casts to Null<T> and replace them by
-	a call to the new Null<T> creation;
-	Also casts from Null<T> to T or direct uses of Null<T> (call, field access, array access, closure)
-	will result in the actual value being accessed
-	For compatibility with the C# target, HardNullable will accept both Null<T> and haxe.lang.Null<T> types
-
-	dependencies:
-		Needs to be run after all cast detection modules
-*)
-let name = "hard_nullable"
-let priority = solve_deps name [DAfter CastDetect.ReturnCast.priority]
-
-let rec is_null_t gen t = match gen.greal_type t with
-	| TAbstract( { a_path = ([], "Null") }, [of_t])
-	| TInst( { cl_path = (["haxe";"lang"], "Null") }, [of_t]) ->
-		let rec take_off_null t =
-			match is_null_t gen t with | None -> t | Some s -> take_off_null s
-		in
-
-		Some (take_off_null of_t)
-	| TMono r -> (match r.tm_type with | Some t -> is_null_t gen t | None -> None)
-	| TLazy f -> is_null_t gen (lazy_type f)
-	| TType (t, tl) ->
-		is_null_t gen (apply_typedef t tl)
-	| _ -> None
-
-let follow_addon gen t =
-	let rec strip_off_nullable t =
-		let t = gen.gfollow#run_f t in
-		match t with
-			(* haxe.lang.Null<haxe.lang.Null<>> wouldn't be a valid construct, so only follow Null<> *)
-			| TAbstract ( { a_path = ([], "Null") }, [of_t] ) -> strip_off_nullable of_t
-			| _ -> t
-	in
-
-	match t with
-		| TAbstract( ({ a_path = ([], "Null") } as tab), [of_t]) ->
-			Some( TAbstract(tab, [ strip_off_nullable of_t ]) )
-		| _ -> None
-
-let configure gen unwrap_null wrap_val null_to_dynamic has_value opeq_handler =
-	gen.gfollow#add (name ^ "_follow") PZero (follow_addon gen);
-
-	let is_null_t = is_null_t gen in
-	let is_string t = match gen.greal_type t with
-		| TInst({ cl_path=([],"String") },_) -> true
-		| _ -> false
-	in
-	let handle_unwrap to_t e =
-		let e_null_t = get (is_null_t e.etype) in
-		match gen.greal_type to_t with
-			| TDynamic _ | TMono _ | TAnon _ ->
-				(match e_null_t with
-					| TDynamic _ | TMono _ | TAnon _ ->
-						gen.ghandle_cast to_t e_null_t (unwrap_null e)
-					| _ -> null_to_dynamic e
-				)
-			| _ ->
-				gen.ghandle_cast to_t e_null_t (unwrap_null e)
-	in
-
-	let handle_wrap e t =
-		match e.eexpr with
-			| TConst(TNull) ->
-				wrap_val e t false
-			| _ ->
-				wrap_val e t true
-	in
-
-	let cur_block = ref [] in
-	let add_tmp v e p =
-		cur_block := { eexpr = TVar(v,e); etype = gen.gcon.basic.tvoid; epos = p } :: !cur_block
-	in
-	let get_local e = match e.eexpr with
-		| TLocal _ ->
-			e, e
-		| _ ->
-			let v = mk_temp "nulltmp" e.etype in
-			add_tmp v (Some (null e.etype e.epos)) e.epos;
-			let local = { e with eexpr = TLocal(v) } in
-			mk_paren { e with eexpr = TBinop(Ast.OpAssign, local, e) }, local
-	in
-	let rec run e =
-		match e.eexpr with
-			| TBlock(bl) ->
-				let lst = !cur_block in
-				cur_block := [];
-				List.iter (fun e ->
-					let e = run e in
-					cur_block := (e :: !cur_block)
-				) bl;
-				let ret = !cur_block in
-				cur_block := lst;
-				{ e with eexpr = TBlock(List.rev ret) }
-			| TCast(v, _) ->
-				let v = match v.eexpr with
-					| TLocal l -> { v with etype = l.v_type }
-					| _ -> v
-				in
-				let null_et = is_null_t e.etype in
-				let null_vt = is_null_t v.etype in
-				(match null_vt, null_et with
-					| Some(vt), None when is_string e.etype ->
-						let v = run v in
-						{ e with eexpr = TCast(null_to_dynamic v,None) }
-					| Some(vt), None ->
-						(match v.eexpr with
-							(* is there an unnecessary cast to Nullable? *)
-							| TCast(v2, _) ->
-								run { v with etype = e.etype }
-							| _ ->
-								handle_unwrap e.etype (run v)
-						)
-					| None, Some(et) ->
-						handle_wrap (run v) et
-					| Some(vt), Some(et) when not (type_iseq (run_follow gen vt) (run_follow gen et)) ->
-						(* check if has value and convert *)
-						let vlocal_fst, vlocal = get_local (run v) in
-						{
-							eexpr = TIf(
-								has_value vlocal_fst,
-								handle_wrap (mk_cast et (unwrap_null vlocal)) et,
-								Some( handle_wrap (null et e.epos) et ));
-							etype = e.etype;
-							epos = e.epos
-						}
-					| _ ->
-						Type.map_expr run e
-				)
-			| TField(ef, field) when is_some (is_null_t ef.etype) ->
-				let to_t = get (is_null_t ef.etype) in
-				{ e with eexpr = TField(handle_unwrap to_t (run ef), field) }
-			| TCall(ecall, params) when is_some (is_null_t ecall.etype) ->
-				let to_t = get (is_null_t ecall.etype) in
-				{ e with eexpr = TCall(handle_unwrap to_t (run ecall), List.map run params) }
-			| TArray(earray, p) when is_some (is_null_t earray.etype) ->
-				let to_t = get (is_null_t earray.etype) in
-				{ e with eexpr = TArray(handle_unwrap to_t (run earray), p) }
-			| TBinop(op, e1, e2) ->
-				let e1_t = is_null_t e1.etype in
-				let e2_t = is_null_t e2.etype in
-
-				(match op with
-					| Ast.OpAssign
-					| Ast.OpAssignOp _ ->
-						(match e1_t, e2_t with
-							| Some t1, Some t2 ->
-								(match op with
-									| Ast.OpAssign ->
-										Type.map_expr run e
-									| Ast.OpAssignOp op ->
-										(match e1.eexpr with
-											| TLocal _ ->
-												{ e with eexpr = TBinop( Ast.OpAssign, e1, handle_wrap { e with eexpr = TBinop (op, handle_unwrap t1 e1, handle_unwrap t2 (run e2) ) } t1 ) }
-											| _ ->
-												let v, e1, evars = match e1.eexpr with
-													| TField(ef, f) ->
-														let v = mk_temp "nullbinop" ef.etype in
-														v, { e1 with eexpr = TField(mk_local v ef.epos, f) }, ef
-													| _ ->
-														let v = mk_temp "nullbinop" e1.etype in
-														v, mk_local v e1.epos, e1
-												in
-												{ e with eexpr = TBlock([
-													{ eexpr = TVar(v, Some evars); etype = gen.gcon.basic.tvoid; epos = e.epos };
-													{ e with eexpr = TBinop( Ast.OpAssign, e1, handle_wrap { e with eexpr = TBinop (op, handle_unwrap t1 e1, handle_unwrap t2 (run e2) ) } t1 ) }
-												]) }
-										)
-									| _ -> Globals.die "" __LOC__
-								)
-
-							| _ ->
-								Type.map_expr run e (* casts are already dealt with normal CastDetection module *)
-						)
-					| Ast.OpEq | Ast.OpNotEq ->
-						(match e1.eexpr, e2.eexpr with
-							| TConst(TNull), _ when is_some e2_t ->
-								let e = has_value (run e2) in
-								if op = Ast.OpEq then
-									{ e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) }
-								else
-									e
-							| _, TConst(TNull) when is_some e1_t ->
-								let e = has_value (run e1) in
-								if op = Ast.OpEq then
-									{ e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) }
-								else
-									e
-							| _ when is_some e1_t || is_some e2_t ->
-									let e1, e2 =
-										if not (is_some e1_t) then
-											run e2, handle_wrap (run e1) (get e2_t)
-										else if not (is_some e2_t) then
-											run e1, handle_wrap (run e2) (get e1_t)
-										else
-											run e1, run e2
-									in
-									let e = opeq_handler e1 e2 in
-									if op = Ast.OpEq then
-										{ e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) }
-									else
-										e
-							| _ ->
-								Type.map_expr run e
-						)
-					| Ast.OpAdd when is_string e1.etype || is_string e2.etype ->
-						let e1 = if is_some e1_t then
-							null_to_dynamic (run e1)
-						else
-							run e1
-						in
-						let e2 = if is_some e2_t then
-							null_to_dynamic (run e2)
-						else
-							run e2
-						in
-						let e_t = is_null_t e.etype in
-						if is_some e_t then
-							wrap_val { eexpr = TBinop(op,e1,e2); etype = get e_t; epos = e.epos } (get e_t) true
-						else
-							{ e with eexpr = TBinop(op,e1,e2) }
-					| _ ->
-						let e1 = if is_some e1_t then
-							handle_unwrap (get e1_t) (run e1)
-						else run e1 in
-						let e2 = if is_some e2_t then
-							handle_unwrap (get e2_t) (run e2)
-						else
-							run e2 in
-
-						(* if it is Null<T>, we need to convert the result again to null *)
-						let e_t = (is_null_t e.etype) in
-						if is_some e_t then
-							wrap_val { eexpr = TBinop(op, e1, e2); etype = get e_t; epos = e.epos } (get e_t) true
-						else
-							{ e with eexpr = TBinop(op, e1, e2) }
-				)
-			(*| TUnop( (Ast.Increment as op)*)
-			| _ -> Type.map_expr run e
-	in
-	let run e = match e.eexpr with
-		| TFunction tf ->
-			run { e with eexpr = TFunction { tf with tf_expr = mk_block tf.tf_expr } }
-		| TBlock _ ->
-			run e
-		| _ -> match run (mk_block e) with
-			| { eexpr = TBlock([e]) } -> e
-			| e -> e
-	in
-	gen.gsyntax_filters#add name (PCustom priority) run

+ 0 - 239
src/codegen/gencommon/initFunction.ml

@@ -1,239 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Type
-open Codegen
-open Texpr.Builder
-open Gencommon
-
-(*
-	This module will take proper care of the init function, by taking off all expressions from static vars and putting them
-	in order in the init function.
-
-	It will also initialize dynamic functions, both by putting them in the constructor and in the init function
-
-	depends on:
-		(syntax) must run before ExprStatement module
-		(ok) must run before OverloadingConstructor module so the constructor can be in the correct place
-		(syntax) must run before FunctionToClass module
-*)
-
-let ensure_simple_expr com e =
-	let rec iter e =
-		match e.eexpr with
-		| TConst _ | TLocal _ | TArray _ | TBinop _
-		| TField _ | TTypeExpr _ | TParenthesis _ | TCast _ | TMeta _
-		| TCall _ | TNew _ | TUnop _ | TIdent _ ->
-			Type.iter iter e
-		| _ ->
-			print_endline (debug_expr e);
-			com.error "Expression is too complex for a readonly variable initialization" e.epos
-	in
-	iter e
-
-let handle_override_dynfun acc e this field =
-	let v = mk_temp ("super_" ^ field) e.etype in
-	add_var_flag v  VCaptured;
-
-	let add_expr = ref None in
-
-	let rec loop e =
-		match e.eexpr with
-		| TField ({ eexpr = TConst TSuper }, f) ->
-			let n = field_name f in
-			if n <> field then Globals.die "" __LOC__;
-			if Option.is_none !add_expr then
-				add_expr := Some { e with eexpr = TVar(v, Some this) };
-			mk_local v e.epos
-		| TConst TSuper -> Globals.die "" __LOC__
-		| _ -> Type.map_expr loop e
-	in
-	let e = loop e in
-
-	match !add_expr with
-	| None -> e :: acc
-	| Some add_expr -> add_expr :: e :: acc
-
-let handle_class gen cl =
-	let com = gen.gcon in
-	let init = match cl.cl_init with
-		| None -> []
-		| Some i -> [i]
-	in
-	let init = List.fold_left (fun acc cf ->
-		match cf.cf_kind with
-			| Var v when Meta.has Meta.ReadOnly cf.cf_meta ->
-					if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then gen.gwarning WGenerator "@:readOnly variable declared without `never` setter modifier" cf.cf_pos;
-					(match cf.cf_expr with
-					| None -> gen.gwarning WGenerator "Uninitialized readonly variable" cf.cf_pos
-					| Some e -> ensure_simple_expr gen.gcon e);
-					acc
-			| Var _
-			| Method MethDynamic when Type.is_physical_field cf ->
-				(match cf.cf_expr with
-				| Some e ->
-					(match cf.cf_params with
-					| [] ->
-						let var = mk (TField (make_static_this cl cf.cf_pos, FStatic(cl,cf))) cf.cf_type cf.cf_pos in
-						let ret = binop Ast.OpAssign var e cf.cf_type cf.cf_pos in
-						cf.cf_expr <- None;
-						ret :: acc
-					| _ ->
-						let params = List.map (fun _ -> t_dynamic) cf.cf_params in
-						let fn = apply_params cf.cf_params params in
-						let var = mk (TField (make_static_this cl cf.cf_pos, FStatic(cl,cf))) (fn cf.cf_type) cf.cf_pos in
-						let rec change_expr e =
-							Type.map_expr_type change_expr fn (fun v -> v.v_type <- fn v.v_type; v) e
-						in
-						let ret = binop Ast.OpAssign var (change_expr e) (fn cf.cf_type) cf.cf_pos in
-						cf.cf_expr <- None;
-						ret :: acc)
-				| None -> acc)
-			| _ -> acc
-	) init cl.cl_ordered_statics in
-	let init = List.rev init in
-	(match init with
-	| [] -> cl.cl_init <- None
-	| _ -> cl.cl_init <- Some (mk (TBlock init) com.basic.tvoid cl.cl_pos));
-
-	(* FIXME: find a way to tell OverloadingConstructor to execute this code even with empty constructors *)
-	let vars, funs = List.fold_left (fun (acc_vars,acc_funs) cf ->
-		match cf.cf_kind with
-		| Var v when Meta.has Meta.ReadOnly cf.cf_meta ->
-				if v.v_write <> AccNever && not (Meta.has Meta.CoreApi cl.cl_meta) then gen.gwarning WGenerator "@:readOnly variable declared without `never` setter modifier" cf.cf_pos;
-				Option.may (ensure_simple_expr com) cf.cf_expr;
-				(acc_vars,acc_funs)
-		| Var _
-		| Method MethDynamic ->
-			let is_var = match cf.cf_kind with Var _ -> true | _ -> false in
-			(match cf.cf_expr, cf.cf_params with
-			| Some e, [] ->
-				let var = mk (TField ((mk (TConst TThis) (TInst (cl, extract_param_types cl.cl_params)) cf.cf_pos), FInstance(cl, extract_param_types cl.cl_params, cf))) cf.cf_type cf.cf_pos in
-				let ret = binop Ast.OpAssign var e cf.cf_type cf.cf_pos in
-				cf.cf_expr <- None;
-				let is_override = has_class_field_flag cf CfOverride in
-
-				if is_override then begin
-					cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields;
-					cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
-					acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name
-				end else if is_var then
-					ret :: acc_vars, acc_funs
-				else
-					acc_vars, ret :: acc_funs
-			| Some e, _ ->
-				let params = List.map (fun _ -> t_dynamic) cf.cf_params in
-				let fn = apply_params cf.cf_params params in
-				let var = mk (TField ((mk (TConst TThis) (TInst (cl, extract_param_types cl.cl_params)) cf.cf_pos), FInstance(cl, extract_param_types cl.cl_params, cf))) cf.cf_type cf.cf_pos in
-				let rec change_expr e =
-					Type.map_expr_type (change_expr) fn (fun v -> v.v_type <- fn v.v_type; v) e
-				in
-
-				let ret = binop Ast.OpAssign var (change_expr e) (fn cf.cf_type) cf.cf_pos in
-				cf.cf_expr <- None;
-				let is_override = has_class_field_flag cf CfOverride in
-
-				if is_override then begin
-					cl.cl_ordered_fields <- List.filter (fun f -> f.cf_name <> cf.cf_name) cl.cl_ordered_fields;
-					cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
-					acc_vars, handle_override_dynfun acc_funs ret var cf.cf_name
-				end else if is_var then
-					ret :: acc_vars, acc_funs
-				else
-					acc_vars, ret :: acc_funs
-			| None, _ -> acc_vars,acc_funs)
-		| _ -> acc_vars,acc_funs
-	) ([],[]) cl.cl_ordered_fields
-	in
-	(* let vars = List.rev vars in *)
-	(* let funs = List.rev funs in *)
-	(* see if there is any *)
-	(match vars, funs with
-	| [], [] -> ()
-	| _ ->
-		(* if there is, we need to find the constructor *)
-		let ctors =
-			match cl.cl_constructor with
-			| Some ctor ->
-				ctor
-			| None ->
-				try
-					let sctor, sup, stl = OverloadingConstructor.prev_ctor cl (extract_param_types cl.cl_params) in
-					let ctor = OverloadingConstructor.clone_ctors com sctor sup stl cl in
-					cl.cl_constructor <- Some ctor;
-					ctor
-				with Not_found ->
-					let ctor = mk_class_field "new" (TFun([], com.basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in
-					ctor.cf_expr <- Some
-					{
-						eexpr = TFunction {
-							tf_args = [];
-							tf_type = com.basic.tvoid;
-							tf_expr = { eexpr = TBlock[]; etype = com.basic.tvoid; epos = cl.cl_pos };
-						};
-						etype = ctor.cf_type;
-						epos = ctor.cf_pos;
-					};
-					cl.cl_constructor <- Some ctor;
-					ctor
-		in
-		let process ctor =
-			let func =
-				match ctor.cf_expr with
-				| Some ({ eexpr = TFunction tf } as e) ->
-					let rec add_fn e =
-						match e.eexpr with
-						| TBlock(hd :: tl) ->
-							(match hd.eexpr with
-							| TCall ({ eexpr = TConst TSuper }, _) ->
-								let tl_block = { e with eexpr = TBlock(tl) } in
-								if not (OverloadingConstructor.descends_from_native_or_skipctor cl) then
-									{ e with eexpr = TBlock (vars @ (hd :: (funs @ [tl_block]))) }
-								else
-									{ e with eexpr = TBlock (hd :: (vars @ funs @ [tl_block])) }
-							| TBlock _ ->
-								let tl_block = { e with eexpr = TBlock(tl) } in
-								{ e with eexpr = TBlock ((add_fn hd) :: [tl_block]) }
-							| _ ->
-								{ e with eexpr = TBlock (vars @ funs @ [{ e with eexpr = TBlock(hd :: tl) }]) })
-						| _ ->
-							Type.concat { e with eexpr = TBlock (vars @ funs) } { e with eexpr = TBlock([e]) }
-					in
-					let tf_expr = add_fn (mk_block tf.tf_expr) in
-					{ e with eexpr = TFunction { tf with tf_expr = tf_expr } }
-				| _ ->
-					Globals.die "" __LOC__
-			in
-			ctor.cf_expr <- Some func
-		in
-		List.iter process (ctors :: ctors.cf_overloads)
-	)
-
-let mod_filter gen md =
-	match md with
-	| TClassDecl cl when not (has_class_flag cl CExtern) ->
-		handle_class gen cl
-	| _ -> ()
-
-let name = "init_funcs"
-let priority = solve_deps name [DBefore OverloadingConstructor.priority]
-
-let configure gen =
-	let run = (fun md -> mod_filter gen md; md) in
-	gen.gmodule_filters#add name (PCustom priority) run

+ 0 - 86
src/codegen/gencommon/intDivisionSynf.ml

@@ -1,86 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Ast
-open Type
-open Gencommon
-
-(*
-	On targets that support int division, this module will force a float division to be performed.
-	It will also look for casts to int or use of Std.int() to optimize this kind of operation.
-
-	dependencies:
-		since it depends on nothing, but many modules might generate division expressions,
-		it will be one of the last modules to run
-*)
-let init com =
-	let rec is_int e =
-		let rec is_int_type t =
-			match follow t with
-				| TInst ({ cl_path = (["haxe";"lang"],"Null") }, [t]) ->
-					is_int_type t
-				| t ->
-					like_int t && not (like_i64 t)
-		in
-		is_int_type e.etype || begin
-			match e.eexpr with
-			| TUnop (_, _, e) -> is_int e
-			| _ -> false
-		end
-	in
-	let rec is_exactly_int e =
-		match follow e.etype with
-		| TAbstract ({ a_path = ([],"Int") }, []) -> true
-		| _ ->
-			match e.eexpr with
-			| TUnop (_, _, e) -> is_exactly_int e
-			| _ -> false
-	in
-	let rec run e =
-		match e.eexpr with
-		| TBinop ((OpDiv as op), e1, e2) when is_int e1 && is_int e2 ->
-			{ e with eexpr = TBinop (op, mk_cast com.basic.tfloat (run e1), run e2) }
-		| TCall (
-				{ eexpr = TField (_, FStatic ({ cl_path = ([], "Std") }, { cf_name = "int" })) },
-				[ { eexpr = TBinop ((OpDiv as op), e1, e2) } as ebinop ]
-			) when is_int e1 && is_int e2 ->
-			let e = { ebinop with eexpr = TBinop (op, run e1, run e2); etype = com.basic.tint } in
-			if not (is_exactly_int e1 && is_exactly_int e2) then
-				mk_cast com.basic.tint e
-			else
-				e
-		| TCast ({ eexpr = TBinop((OpDiv as op), e1, e2) } as ebinop, _ )
-		| TCast ({ eexpr = TBinop(((OpAssignOp OpDiv) as op), e1, e2) } as ebinop, _ ) when is_int e1 && is_int e2 && is_int e ->
-			let ret = { ebinop with eexpr = TBinop (op, run e1, run e2); etype = e.etype } in
-			if not (is_exactly_int e1 && is_exactly_int e2) then
-				mk_cast e.etype ret
-			else
-				Type.map_expr run e
-
-		| _ ->
-			Type.map_expr run e
-	in
-	run
-
-let name = "int_division_synf"
-let priority = solve_deps name [ DAfter ExpressionUnwrap.priority; DAfter ObjectDeclMap.priority; DAfter ArrayDeclSynf.priority ]
-
-let configure gen =
-	let run = init gen.gcon in
-	gen.gsyntax_filters#add name (PCustom priority) run

+ 0 - 43
src/codegen/gencommon/interfaceProps.ml

@@ -1,43 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Globals
-open Type
-
-(*
-	This module filter will go through all declared properties, and see if they are conforming to a native interface.
-	If they are, it will add Meta.Property to it.
-*)
-let run = function
-	| TClassDecl cl when not (has_class_flag cl CInterface) && not (has_class_flag cl CExtern) ->
-		let vars = List.fold_left (fun acc (iface,_) ->
-			if Meta.has Meta.CsNative iface.cl_meta then
-				let props = List.filter (fun cf -> match cf.cf_kind with Var { v_read = AccCall } | Var { v_write = AccCall } -> true | _ -> false) iface.cl_ordered_fields in
-				props @ acc
-			else
-				acc
-		) [] cl.cl_implements in
-		if vars <> [] then
-			let vars = List.map (fun cf -> cf.cf_name) vars in
-			List.iter (fun cf -> match cf.cf_kind with
-				| Var { v_read = AccCall } | Var { v_write = AccCall } when List.mem cf.cf_name vars ->
-					cf.cf_meta <- (Meta.Property, [], null_pos) :: cf.cf_meta
-				| _ -> ()
-			) cl.cl_ordered_fields
-	| _ ->
-		()

+ 0 - 84
src/codegen/gencommon/interfaceVarsDeleteModf.ml

@@ -1,84 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Globals
-open Type
-open Gencommon
-
-(* ******************************************* *)
-(* Interface Variables Removal Modf *)
-(* ******************************************* *)
-(*
-	This module filter will take care of sanitizing interfaces for targets that do not support
-	variables declaration in interfaces. By now this will mean that if anything is typed as the interface,
-	and a variable access is made, a FNotFound will be returned for the field_access, so
-	the field will be only accessible by reflection.
-	Speed-wise, ideally it would be best to create getProp/setProp functions in this case and change
-	the AST to call them when accessing by interface. (TODO)
-	But right now it will be accessed by reflection.
-*)
-let name = "interface_vars"
-let priority = solve_deps name []
-
-let configure gen =
-	let run md =
-		match md with
-		| TClassDecl cl when (has_class_flag cl CInterface) ->
-			let to_add = ref [] in
-			let fields = List.filter (fun cf ->
-				match cf.cf_kind with
-				| Var _ when gen.gcon.platform = Cs && Meta.has Meta.Event cf.cf_meta ->
-					true
-				| Var vkind when Type.is_physical_field cf || not (Meta.has Meta.Property cf.cf_meta) ->
-					(match vkind.v_read with
-						| AccCall ->
-							let newcf = mk_class_field ("get_" ^ cf.cf_name) (TFun([],cf.cf_type)) true cf.cf_pos (Method MethNormal) [] in
-							to_add := newcf :: !to_add;
-						| _ -> ()
-					);
-					(match vkind.v_write with
-						| AccCall ->
-							let newcf = mk_class_field ("set_" ^ cf.cf_name) (TFun(["val",false,cf.cf_type],cf.cf_type)) true cf.cf_pos (Method MethNormal) [] in
-							to_add := newcf :: !to_add;
-						| _ -> ()
-					);
-					cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
-					false
-				| Method MethDynamic ->
-					(* TODO OPTIMIZATION - add a `_dispatch` method to the interface which will call the dynamic function itself *)
-					cl.cl_fields <- PMap.remove cf.cf_name cl.cl_fields;
-					false
-				| _ ->
-					true
-			) cl.cl_ordered_fields in
-
-			cl.cl_ordered_fields <- fields;
-
-			List.iter (fun cf ->
-				match field_access gen (TInst(cl,extract_param_types cl.cl_params)) cf.cf_name with
-				| FNotFound | FDynamicField _ ->
-					cl.cl_ordered_fields <- cf :: cl.cl_ordered_fields;
-					cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields
-				| _ ->
-					()
-			) !to_add
-		| _ -> ()
-	in
-	let map md = run md; md in
-	gen.gmodule_filters#add name (PCustom priority) map

+ 0 - 100
src/codegen/gencommon/normalize.ml

@@ -1,100 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Type
-open Gencommon
-
-(*
-	- Filters out enum constructor type parameters from the AST; See Issue #1796
-	- Filters out monomorphs
-	- Filters out all non-whitelisted AST metadata
-
-	dependencies:
-		No dependencies; but it still should be one of the first filters to run,
-		as it will help normalize the AST
-*)
-
-let rec filter_param (stack:t list) t =
-	match t with
-	| TInst({ cl_kind = KTypeParameter _ } as c,_) when Meta.has Meta.EnumConstructorParam c.cl_meta ->
-		t_dynamic
-	| TMono r ->
-		(match r.tm_type with
-		| None -> t_dynamic
-		| Some t -> filter_param stack t)
-	| TInst(_,[]) | TEnum(_,[]) | TAbstract(_,[]) ->
-		t
-	| TType({ t_path = (["haxe";"extern"],"Rest") },_) ->
-		filter_param stack (follow t)
-	| TType(td,tl) ->
-		TType(td,List.map (filter_param stack) tl)
-	| TInst(c,tl) ->
-		TInst(c,List.map (filter_param stack) tl)
-	| TEnum(e,tl) ->
-		TEnum(e,List.map (filter_param stack) tl)
-	| TAbstract({ a_path = (["haxe"],"Rest") } as a,tl) ->
-		TAbstract(a, List.map (filter_param stack) tl)
-	| TAbstract({a_path = [],"Null"} as a,[t]) ->
-		TAbstract(a,[filter_param stack t])
-	| TAbstract(a,tl) when (Meta.has Meta.MultiType a.a_meta) ->
-		filter_param stack (Abstract.get_underlying_type a tl)
-	| TAbstract(a,tl) ->
-		TAbstract(a, List.map (filter_param stack) tl)
-	| TAnon a ->
-		let fields = PMap.map (fun f -> { f with cf_type = filter_param stack f.cf_type }) a.a_fields in
-		mk_anon ~fields a.a_status
-	| TFun(args,ret) ->
-		TFun(List.map (fun (n,o,t) -> (n,o,filter_param stack t)) args, filter_param stack ret)
-	| TDynamic _ ->
-		t
-	| TLazy f ->
-		filter_param stack (lazy_type f)
-
-let filter_param t = filter_param [] t
-
-let init_expr_filter allowed_metas =
-	let rec run e =
-		match e.eexpr with
-		| TMeta ((m,_,_), e) when not (Hashtbl.mem allowed_metas m) ->
-			run e
-		| _ ->
-			map_expr_type (fun e -> run e) filter_param (fun v -> v.v_type <- filter_param v.v_type; v) e
-	in
-	run
-
-let type_filter = function
-	| TClassDecl cl ->
-		let rec map cf =
-			cf.cf_type <- filter_param cf.cf_type;
-			List.iter map cf.cf_overloads
-		in
-		List.iter map cl.cl_ordered_fields;
-		List.iter map cl.cl_ordered_statics;
-		Option.may map cl.cl_constructor
-	| _ ->
-		()
-
-let name = "normalize_type"
-let priority = max_dep
-
-let configure gen ~allowed_metas =
-	let run = init_expr_filter allowed_metas in
-	gen.gexpr_filters#add name (PCustom priority) run;
-
-	let map md = type_filter md; md in
-	gen.gmodule_filters#add name (PCustom priority) map

+ 0 - 37
src/codegen/gencommon/objectDeclMap.ml

@@ -1,37 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Type
-open Gencommon
-
-(* ******************************************* *)
-(* Object Declaration Mapper *)
-(* ******************************************* *)
-let name = "object_decl_map"
-let priority = solve_deps name []
-
-let configure gen map_fn =
-	let rec run e =
-		match e.eexpr with
-		| TObjectDecl odecl ->
-			let e = Type.map_expr run e in
-			(match e.eexpr with TObjectDecl odecl -> map_fn e odecl | _ -> Globals.die "" __LOC__)
-		| _ ->
-			Type.map_expr run e
-	in
-	gen.gsyntax_filters#add name (PCustom priority) run

+ 0 - 460
src/codegen/gencommon/overloadingConstructor.ml

@@ -1,460 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Common
-open Type
-open Codegen
-open Gencommon
-
-(* ******************************************* *)
-(* overloading reflection constructors *)
-(* ******************************************* *)
-(*
-	this module works on languages that support function overloading and
-	enable function hiding via static functions.
-	it takes the constructor body out of the constructor and adds it to a special ctor
-	static function. The static function will receive the same parameters as the constructor,
-	plus the special "me" var, which will replace "this"
-
-	Then it always adds two constructors to the class: one that receives a special marker class,
-	indicating that the object should be constructed without executing constructor body,
-	and one that executes its normal constructor.
-	Both will only include a super() call to the superclasses' emtpy constructor.
-
-	This enables two things:
-		empty construction without the need of incompatibility with the platform's native construction method
-		the ability to call super() constructor in any place in the constructor
-*)
-
-let rec prev_ctor c tl =
-	match c.cl_super with
-	| None ->
-		raise Not_found
-	| Some (sup,stl) ->
-		let stl = List.map (apply_params c.cl_params tl) stl in
-		match sup.cl_constructor with
-		| None -> prev_ctor sup stl
-		| Some ctor -> ctor, sup, stl
-
-let make_static_ctor_name cl =
-	let name = mk_internal_name "hx" "ctor" in
-	name ^ "_" ^ (String.concat "_" (fst cl.cl_path)) ^ "_" ^ (snd cl.cl_path)
-
-(* replaces super() call with last static constructor call *)
-let replace_super_call com c tl with_params me p follow_type =
-	let rec loop_super c tl =
-		match c.cl_super with
-		| None ->
-			raise Not_found
-		| Some(sup,stl) ->
-			let stl = List.map (apply_params c.cl_params tl) stl in
-			try
-				let static_ctor_name = make_static_ctor_name sup in
-				sup, stl, PMap.find static_ctor_name sup.cl_statics
-			with Not_found ->
-				loop_super sup stl
-	in
-	let sup, stl, cf = loop_super c tl in
-	let with_params = (mk (TLocal me) me.v_type p) :: with_params in
-	let cf =
-		try
-			(* choose best super function *)
-			List.iter (fun e -> replace_mono e.etype) with_params;
-			List.find (fun cf ->
-				replace_mono cf.cf_type;
-				let args, _ = get_fun (apply_params cf.cf_params stl cf.cf_type) in
-				try
-					List.for_all2 (fun (_,_,t) e -> try
-						let e_etype = follow_type e.etype in
-						let t = follow_type t in
-						unify e_etype t; true
-					with Unify_error _ ->
-						false
-					) args with_params
-				with Invalid_argument _ ->
-					false
-			) (cf :: cf.cf_overloads)
-		with Not_found ->
-			com.error "No suitable overload for the super call arguments was found" p; cf
-	in
-	{
-		eexpr = TCall(
-			{
-				eexpr = TField(Texpr.Builder.make_static_this sup p, FStatic(sup,cf));
-				etype = apply_params cf.cf_params stl cf.cf_type;
-				epos = p
-			},
-			with_params
-		);
-		etype = com.basic.tvoid;
-		epos = p;
-	}
-
-(* will create a static counterpart of 'ctor', and replace its contents to a call to the static version*)
-let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
-	match Meta.has Meta.SkipCtor ctor.cf_meta with
-	| true -> ()
-	| false when is_none ctor.cf_expr -> ()
-	| false ->
-		let static_ctor_name = make_static_ctor_name cl in
-		(* create the static constructor *)
-		let ctor_types = List.map (fun tp -> {tp with ttp_type = TInst(map_param (get_cl_t tp.ttp_type), [])}) cl.cl_params in
-		let ctor_type_params = extract_param_types ctor_types in
-		List.iter (function {ttp_type=TInst(c,[])} -> (
-			match c.cl_kind with
-			| KTypeParameter (hd :: tail) ->
-				let before = hd :: tail in
-				let after = List.map (apply_params cl.cl_params ctor_type_params) (before) in
-				c.cl_kind <- KTypeParameter(after)
-			| _ -> ())
-		| _ -> ()) ctor_types;
-		let me = alloc_var "__hx_this" (TInst(cl, extract_param_types ctor_types)) in
-		add_var_flag me VCaptured;
-
-		let fn_args, _ = get_fun ctor.cf_type in
-		let ctor_params = extract_param_types ctor_types in
-		let fn_type = TFun((me.v_name,false, me.v_type) :: List.map (fun (n,o,t) -> (n,o,apply_params cl.cl_params ctor_params t)) fn_args, com.basic.tvoid) in
-		let cur_tf_args = match ctor.cf_expr with
-		| Some { eexpr = TFunction(tf) } -> tf.tf_args
-		| _ -> Globals.die "" __LOC__
-		in
-
-		let changed_tf_args = List.map (fun (v,_) -> (v,None)) cur_tf_args in
-
-		let local_map = Hashtbl.create (List.length cur_tf_args) in
-		let static_tf_args = (me, None) :: List.map (fun (v,b) ->
-			let new_v = alloc_var v.v_name (apply_params cl.cl_params ctor_params v.v_type) in
-			add_var_flag new_v VCaptured;
-			Hashtbl.add local_map v.v_id new_v;
-			(new_v, b)
-		) cur_tf_args in
-
-		let static_ctor = mk_class_field ~static:true static_ctor_name fn_type false ctor.cf_pos (Method MethNormal) ctor_types in
-		let static_ctor_meta = if has_class_flag cl CFinal then Meta.Private else Meta.Protected in
-		static_ctor.cf_meta <- (static_ctor_meta,[],ctor.cf_pos) :: static_ctor.cf_meta;
-
-		(* change ctor contents to reference the 'me' var instead of 'this' *)
-		let actual_super_call = ref None in
-		let rec map_expr ~is_first e = match e.eexpr with
-			| TCall (({ eexpr = TConst TSuper } as tsuper), params) -> (try
-				let params = List.map (fun e -> map_expr ~is_first:false e) params in
-				actual_super_call := Some { e with eexpr = TCall(tsuper, [empty_ctor_expr]) };
-				replace_super_call com cl ctor_params params me e.epos follow_type
-			with | Not_found ->
-				(* last static function was not found *)
-				actual_super_call := Some e;
-				if not is_first then
-					com.error "Super call must be the first call when extending native types" e.epos;
-				{ e with eexpr = TBlock([]) })
-			| TFunction tf when is_first ->
-				do_map ~is_first:true e
-			| TConst TThis ->
-				mk_local me e.epos
-			| TBlock (fst :: bl) ->
-				let fst = map_expr ~is_first:is_first fst in
-				{ e with eexpr = TBlock(fst :: List.map (fun e -> map_expr ~is_first:false e) bl); etype = apply_params cl.cl_params ctor_params e.etype }
-			| _ ->
-				do_map e
-		and do_map ?(is_first=false) e =
-			let do_t = apply_params cl.cl_params ctor_params in
-			let do_v v = try
-					Hashtbl.find local_map v.v_id
-				with | Not_found ->
-					v.v_type <- do_t v.v_type; v
-			in
-			Type.map_expr_type (map_expr ~is_first:is_first) do_t do_v e
-		in
-
-		let expr = do_map ~is_first:true (get ctor.cf_expr) in
-		let expr = match expr.eexpr with
-		| TFunction(tf) ->
-			{ expr with etype = fn_type; eexpr = TFunction({ tf with tf_args = static_tf_args }) }
-		| _ -> Globals.die "" __LOC__ in
-		static_ctor.cf_expr <- Some expr;
-		(* add to the statics *)
-		(try
-			let stat = PMap.find static_ctor_name cl.cl_statics in
-			stat.cf_overloads <- static_ctor :: stat.cf_overloads
-		with | Not_found ->
-			cl.cl_ordered_statics <- static_ctor :: cl.cl_ordered_statics;
-			cl.cl_statics <- PMap.add static_ctor_name static_ctor cl.cl_statics);
-		(* change current super call *)
-		match ctor.cf_expr with
-		| Some({ eexpr = TFunction(tf) } as e) ->
-			let block_contents, p = match !actual_super_call with
-			| None -> [], ctor.cf_pos
-			| Some super -> [super], super.epos
-			in
-			let el_args =
-				let rec loop fn_args cur_args =
-					match cur_args with
-					| [] -> []
-					| (v,_) :: cur_args ->
-						let local = mk_local v p in
-						match fn_args, cur_args with
-						| [_,_,t], [] when ExtType.is_rest (follow t) ->
-							[mk (TUnop(Spread,Prefix,local)) v.v_type p]
-						| [], _ ->
-							local :: loop fn_args cur_args
-						| _ :: fn_args, _ ->
-							local :: loop fn_args cur_args
-				in
-				loop fn_args cur_tf_args
-			in
-			let block_contents = block_contents @ [{
-				eexpr = TCall(
-					{
-						eexpr = TField(
-							Texpr.Builder.make_static_this cl p,
-							FStatic(cl, static_ctor));
-						etype = apply_params static_ctor.cf_params (extract_param_types cl.cl_params) static_ctor.cf_type;
-						epos = p
-					},
-					[{ eexpr = TConst TThis; etype = TInst(cl, extract_param_types cl.cl_params); epos = p }]
-					@ el_args
-				);
-				etype = com.basic.tvoid;
-				epos = p
-			}] in
-			ctor.cf_expr <- Some { e with eexpr = TFunction({ tf with tf_expr = { tf.tf_expr with eexpr = TBlock block_contents }; tf_args = changed_tf_args }) }
-		| _ -> Globals.die "" __LOC__
-
-(* makes constructors that only call super() for the 'ctor' argument *)
-let clone_ctors com ctor sup stl cl =
-	let rec clone cf =
-		let ncf = mk_class_field "new" (apply_params sup.cl_params stl cf.cf_type) (has_class_field_flag cf CfPublic) cf.cf_pos cf.cf_kind cf.cf_params in
-		if Meta.has Meta.Protected cf.cf_meta then
-			ncf.cf_meta <- (Meta.Protected,[],ncf.cf_pos) :: ncf.cf_meta;
-		let args, ret = get_fun ncf.cf_type in
-		(* single expression: call to super() *)
-		let tf_args = List.map (fun (name,_,t) ->
-			(* the constructor will have no optional arguments, as presumably this will be handled by the underlying expr *)
-			alloc_var name t, None
-		) args in
-		let super_call =
-		{
-			eexpr = TCall(
-				{ eexpr = TConst TSuper; etype = TInst(cl, extract_param_types cl.cl_params); epos = ctor.cf_pos },
-				List.map (fun (v,_) -> mk_local v ctor.cf_pos) tf_args);
-			etype = com.basic.tvoid;
-			epos = ctor.cf_pos;
-		} in
-		ncf.cf_expr <- Some
-		{
-			eexpr = TFunction {
-				tf_args = tf_args;
-				tf_type = com.basic.tvoid;
-				tf_expr = mk_block super_call;
-			};
-			etype = ncf.cf_type;
-			epos = ctor.cf_pos;
-		};
-		ncf
-	in
-	(* take off createEmpty *)
-	let all = List.filter (fun cf -> replace_mono cf.cf_type; not (Meta.has Meta.SkipCtor cf.cf_meta)) (ctor :: ctor.cf_overloads) in
-	let clones = List.map clone all in
-	match clones with
-	| [] ->
-		(* raise Not_found *)
-		Globals.die "" __LOC__ (* should never happen *)
-	| cf :: [] -> cf
-	| cf :: overl ->
-		add_class_field_flag cf CfOverload;
-		cf.cf_overloads <- overl; cf
-
-let rec descends_from_native_or_skipctor cl =
-	not (is_hxgen (TClassDecl cl)) || Meta.has Meta.SkipCtor cl.cl_meta || match cl.cl_super with
-	| None -> false
-	| Some(c,_) -> descends_from_native_or_skipctor c
-
-let ensure_super_is_first com cf =
-	let rec loop e =
-		match e.eexpr with
-		| TBlock (b :: block) ->
-			loop b
-		| TBlock []
-		| TCall({ eexpr = TConst TSuper },_) -> ()
-		| _ ->
-			com.error "Types that derive from a native class must have its super() call as the first statement in the constructor" cf.cf_pos
-	in
-	match cf.cf_expr with
-	| None -> ()
-	| Some e -> Type.iter loop e
-
-let init com (empty_ctor_type : t) (empty_ctor_expr : texpr) (follow_type : t -> t) =
-	let basic = com.basic in
-	let should_change cl = not (has_class_flag cl CInterface) && (not (has_class_flag cl CExtern) || is_hxgen (TClassDecl cl)) && (match cl.cl_kind with KAbstractImpl _ | KModuleFields _ -> false | _ -> true) in
-	let msize = List.length com.types in
-	let processed, empty_ctors = Hashtbl.create msize, Hashtbl.create msize in
-
-	let rec get_last_empty cl =
-		try
-			Hashtbl.find empty_ctors cl.cl_path
-		with | Not_found ->
-			match cl.cl_super with
-			| None -> raise Not_found
-			| Some (sup,_) -> get_last_empty sup
-	in
-
-	let rec change cl =
-		if not (Hashtbl.mem processed cl.cl_path) then begin
-			Hashtbl.add processed cl.cl_path true;
-
-			(* make sure we've processed the super types *)
-			Option.may (fun (super,_) -> if should_change super then change super) cl.cl_super;
-
-			(* implement static hx_ctor and reimplement constructors *)
-			(try
-				let ctor =
-					match cl.cl_constructor with
-					| Some ctor ->
-						ctor
-					| None ->
-						try
-							let sctor, sup, stl = prev_ctor cl (extract_param_types cl.cl_params) in
-							(* we'll make constructors that will only call super() *)
-							let ctor = clone_ctors com sctor sup stl cl in
-							cl.cl_constructor <- Some ctor;
-							ctor
-						with Not_found -> (* create default constructor *)
-							let ctor = mk_class_field "new" (TFun ([], basic.tvoid)) false cl.cl_pos (Method MethNormal) [] in
-							ctor.cf_expr <- Some {
-								eexpr = TFunction {
-									tf_args = [];
-									tf_type = basic.tvoid;
-									tf_expr = mk (TBlock []) basic.tvoid cl.cl_pos;
-								};
-								etype = ctor.cf_type;
-								epos = ctor.cf_pos;
-							};
-							cl.cl_constructor <- Some ctor;
-							ctor
-				in
-
-				let has_super_constructor =
-					match cl.cl_super with
-						| None -> false
-						| Some (csup,_) -> has_constructor csup
-				in
-
-				(* now that we made sure we have a constructor, exit if native gen *)
-				if not (is_hxgen (TClassDecl cl)) || Meta.has Meta.SkipCtor cl.cl_meta then begin
-					if descends_from_native_or_skipctor cl && has_super_constructor then
-						List.iter (fun cf -> ensure_super_is_first com cf) (ctor :: ctor.cf_overloads);
-					raise Exit
-				end;
-
-				(* if cl descends from a native class, we cannot use the static constructor strategy *)
-				if descends_from_native_or_skipctor cl && has_super_constructor then
-					List.iter (fun cf -> ensure_super_is_first com cf) (ctor :: ctor.cf_overloads)
-				else
-					(* now that we have a current ctor, create the static counterparts *)
-					List.iter (fun cf -> create_static_ctor com ~empty_ctor_expr:empty_ctor_expr cl cf follow_type) (ctor :: ctor.cf_overloads)
-			with Exit -> ());
-
-			(* implement empty ctor *)
-			(try
-				(* now that we made sure we have a constructor, exit if native gen *)
-				if not (is_hxgen (TClassDecl cl)) then raise Exit;
-
-				(* get first *)
-				let empty_type = TFun (["empty",false,empty_ctor_type],basic.tvoid) in
-				let super =
-					match cl.cl_super with
-					| None -> (* implement empty *)
-							[]
-					| Some (sup,_) ->
-						try
-							ignore (get_last_empty sup);
-							let esuper = mk (TConst TSuper) (TInst (cl, extract_param_types cl.cl_params)) cl.cl_pos in
-							[mk (TCall (esuper, [empty_ctor_expr])) basic.tvoid cl.cl_pos]
-						with Not_found ->
-							try
-								(* super type is native: find super constructor with least arguments *)
-								let sctor, sup, stl = prev_ctor cl (extract_param_types cl.cl_params) in
-								let rec loop remaining (best,n) =
-									match remaining with
-									| [] -> best
-									| cf :: r ->
-										let args,_ = get_fun cf.cf_type in
-										if (List.length args) < n then
-											loop r (cf,List.length args)
-										else
-											loop r (best,n)
-								in
-								let args,_ = get_fun sctor.cf_type in
-								let best = loop sctor.cf_overloads (sctor, List.length args) in
-								let args,_ = get_fun (apply_params sup.cl_params stl best.cf_type) in
-								let esuper = mk (TConst TSuper) (TInst (sup, stl)) cl.cl_pos in
-								[mk (TCall (esuper, List.map (fun (n,o,t) -> null t cl.cl_pos) args)) basic.tvoid cl.cl_pos]
-							with Not_found ->
-								(* extends native type, but no ctor found *)
-								[]
-				in
-				let ctor = mk_class_field "new" empty_type false cl.cl_pos (Method MethNormal) [] in
-				ctor.cf_expr <- Some {
-					eexpr = TFunction {
-						tf_type = basic.tvoid;
-						tf_args = [alloc_var "empty" empty_ctor_type, None];
-						tf_expr = mk (TBlock super) basic.tvoid cl.cl_pos
-					};
-					etype = empty_type;
-					epos = cl.cl_pos;
-				};
-				ctor.cf_meta <- [Meta.SkipCtor, [], ctor.cf_pos];
-				Hashtbl.add empty_ctors cl.cl_path ctor;
-				match cl.cl_constructor with
-				| None ->
-					cl.cl_constructor <- Some ctor
-				| Some c ->
-					c.cf_overloads <- ctor :: c.cf_overloads
-			with Exit -> ());
-		end
-	in
-
-	let module_filter md =
-		(match md with
-		| TClassDecl cl when should_change cl ->
-			change cl;
-		| _ ->
-			());
-		md
-	in
-	module_filter
-
-let init_expr_filter create_empty =
-	let rec run e =
-		match e.etype, e.eexpr with
-		| TInst (cl, params), TCall ({ eexpr = TField (_, FStatic ({cl_path = [],"Type"}, {cf_name = "createEmptyInstance"})) }, [{eexpr = TTypeExpr ((TClassDecl cl_arg) as mt_arg) }]) when cl == cl_arg && is_hxgen mt_arg ->
-			create_empty cl params e.epos
-		| _ ->
-			Type.map_expr run e
-	in
-	run
-
-let priority = 0.0
-let name = "overloading_constructor"
-
-let configure gen ~empty_ctor_type ~empty_ctor_expr =
-	gen.gtools.r_create_empty <- (fun cl params pos -> mk (TNew(cl,params,[empty_ctor_expr])) (TInst(cl,params)) pos);
-	let module_filter = init gen.gcon empty_ctor_type empty_ctor_expr (run_follow gen) in
-	gen.gmodule_filters#add name (PCustom priority) module_filter;
-	let expr_filter = init_expr_filter gen.gtools.r_create_empty in
-	gen.gexpr_filters#add name (PCustom priority) expr_filter

+ 0 - 784
src/codegen/gencommon/realTypeParams.ml

@@ -1,784 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Common
-open Ast
-open Type
-open Codegen
-open Texpr.Builder
-open Gencommon
-
-(* ******************************************* *)
-(* Type Parameters *)
-(* ******************************************* *)
-(*
-	This module will handle type parameters. There are lots of changes we need to do to correctly support type parameters:
-
-	traverse will:
-		V Detect when parameterized function calls are made
-		* Detect when a parameterized class instance is being cast to another parameter
-		* Change new<> parameterized function calls
-		*
-
-	extras:
-		* On languages that support "real" type parameters, a Cast function is provided that will convert from a <Dynamic> to the requested type.
-			This cast will call createEmpty with the correct type, and then set each variable to the new form. Some types will be handled specially, namely the Native Array.
-			Other implementations may be delegated to the runtime.
-		* parameterized classes will implement a new interface (with only a Cast<> function added to it), so we can access the <Dynamic> type parameter for them. Also any reference to <Dynamic> will be replaced by a reference to this interface. (also on TTypeExpr - Std.is())
-		* Type parameter renaming to avoid name clash
-		* Detect type parameter casting and call Cast<> instead
-
-	for java:
-		* for specially assigned classes, parameters will be replaced by _d and _i versions of parameterized functions. This will only work for parameterized classes, not functions.
-
-	dependencies:
-		must run after casts are detected. This will be ensured at CastDetect module.
-*)
-(* ******************************************* *)
-(* Real Type Parameters Module *)
-(* ******************************************* *)
-(*
-	This submodule is by now specially made for the .NET platform. There might be other targets that will
-	make use of this, but it IS very specific.
-
-	On the .NET platform, generics are real specialized classes that are JIT compiled. For this reason, we cannot
-	cast from one type parameter to another. Also there is no common type for the type parameters, so for example
-	an instance of type Array<Int> will return false for instance is Array<object> .
-
-	So we need to:
-		1. create a common interface (without type parameters) (e.g. "Array") which will only contain a __Cast<> function, which will cast from one type into another
-		2. Implement the __Cast function. This part is a little hard, as we must identify all type parameter-dependent fields contained in the class and convert them.
-		In most cases the conversion will just be to call .__Cast<>() on the instances, or just a simple cast. But when the instance is a @:nativegen type, there will be no .__Cast
-		function, and we will need to deal with this case either at compile-time (added handlers - specially for NativeArray), or at runtime (adding new runtime handlers)
-		3. traverse the AST looking for casts involving type parameters, and replace them with .__Cast<>() calls. If type is @:nativegen, throw a warning. If really casting from one type parameter to another on a @:nativegen context, throw an error.
-
-
-	special literals:
-		it will use the special literal __typehandle__ that the target must implement in order to run this. This literal is a way to get the typehandle of e.g. the type parameters,
-		so we can compare them. In C# it's the equivalent of typeof(T).TypeHandle (TypeHandle compare is faster than System.Type.Equals())
-
-	dependencies:
-		(module filter) Interface creation must run AFTER enums are converted into classes, otherwise there is no way to tell parameterized enums to implement an interface
-		Must run AFTER CastDetect. This will be ensured per CastDetect
-
-*)
-let name = "real_type_params"
-let priority = max_dep -. 20.
-
-let rec has_type_params t =
-	match follow t with
-		| TInst( { cl_kind = KTypeParameter _ }, _) -> true
-		| TAbstract(_, params)
-		| TEnum(_, params)
-		| TInst(_, params) -> List.exists (fun t -> has_type_params t) params
-		| TFun(args,ret) ->
-			List.exists (fun (n,o,t) -> has_type_params t) args || has_type_params ret
-		| _ -> false
-
-let rec follow_all_md md =
-	let t = match md with
-		| TClassDecl { cl_kind = KAbstractImpl a } ->
-			TAbstract(a, extract_param_types a.a_params)
-		| TClassDecl c ->
-			TInst(c, extract_param_types c.cl_params)
-		| TEnumDecl e ->
-			TEnum(e, extract_param_types e.e_params)
-		| TTypeDecl t ->
-			TType(t, extract_param_types t.t_params)
-		| TAbstractDecl a ->
-			TAbstract(a, extract_param_types a.a_params)
-	in
-	Abstract.follow_with_abstracts t
-
-let rec is_hxgeneric md =
-	match md with
-	| TClassDecl { cl_kind = KAbstractImpl a } ->
-		is_hxgeneric (TAbstractDecl a)
-	| TClassDecl(cl) ->
-		not (Meta.has Meta.NativeGeneric cl.cl_meta)
-	| TEnumDecl(e) ->
-		not (Meta.has Meta.NativeGeneric e.e_meta)
-	| TAbstractDecl(a) when Meta.has Meta.NativeGeneric a.a_meta ->
-		not (Meta.has Meta.NativeGeneric a.a_meta)
-	| md -> match follow_all_md md with
-		| TInst(cl,_) -> is_hxgeneric (TClassDecl cl)
-		| TEnum(e,_) -> is_hxgeneric (TEnumDecl e)
-		| TAbstract(a,_) -> not (Meta.has Meta.NativeGeneric a.a_meta)
-		| _ -> true
-
-type nativegeneric_reason =
-	| ReasonField of string * Type.t
-	| ReasonSuper of Globals.path
-	| ReasonExplicit
-
-exception Cannot_be_native of Globals.path * pos * Globals.path * nativegeneric_reason
-
-let rec set_hxgeneric gen mds isfirst md =
-	let iface_path, raise_pos, raise_if_native = match md with
-		| TClassDecl(cl) -> (try
-			(fst (List.find (fun (cl,_) -> (set_hxgeneric gen mds isfirst (TClassDecl cl) ) = Some(true) ) cl.cl_implements)).cl_path, cl.cl_pos, true
-		with Not_found ->
-			([],""), Globals.null_pos, false)
-		| _ -> ([],""), Globals.null_pos, false
-	in
-	let path = t_path md in
-	if List.exists (fun m -> path = t_path m) mds then begin
-		if isfirst then
-			None (* we still can't determine *)
-		else
-			Some true (* if we're in second pass and still can't determine, it's because it can be hxgeneric *)
-	end else begin
-		let has_unresolved = ref false in
-		let is_false v =
-			match v with
-				| Some false -> true
-				| None -> has_unresolved := true; false
-				| Some true -> false
-		in
-		let mds = md :: mds in
-		match md with
-			| TClassDecl(cl)	->
-				(* first see if any meta is present (already processed) *)
-				if Meta.has Meta.NativeGeneric cl.cl_meta then begin
-					if raise_if_native then raise (Cannot_be_native(path, raise_pos, iface_path, ReasonExplicit));
-					Some false
-				end else if Meta.has Meta.HaxeGeneric cl.cl_meta then
-					Some true
-				else if cl.cl_params = [] && is_hxgen md then
-					(cl.cl_meta <- (Meta.HaxeGeneric,[],cl.cl_pos) :: cl.cl_meta;
-					Some true)
-				else if cl.cl_params = [] then
-					(cl.cl_meta <- (Meta.NativeGeneric, [], cl.cl_pos) :: cl.cl_meta;
-					Some false)
-				else if not (is_hxgen md) then
-					(cl.cl_meta <- (Meta.NativeGeneric, [], cl.cl_pos) :: cl.cl_meta;
-					Some false)
-				else begin
-					(*
-						if it's not present, see if any superclass is nativegeneric.
-						nativegeneric is inherited, while hxgeneric can be later changed to nativegeneric
-					*)
-					(* on the first pass, our job is to find any evidence that makes it not be hxgeneric. Otherwise it will be hxgeneric *)
-					match cl.cl_super with
-						| Some (c,_) when is_false (set_hxgeneric gen mds isfirst (TClassDecl c)) ->
-							if raise_if_native then raise (Cannot_be_native(path, raise_pos, iface_path, ReasonSuper(c.cl_path)));
-							cl.cl_meta <- (Meta.NativeGeneric, [], cl.cl_pos) :: cl.cl_meta;
-							Some false
-						| _ ->
-							(* see if it's a generic class *)
-							match cl.cl_params with
-								| [] ->
-									(* if it's not, then it will follow hxgen *)
-									if is_hxgen (TClassDecl cl) then
-										cl.cl_meta <- (Meta.HaxeGeneric, [], cl.cl_pos) :: cl.cl_meta
-									else
-										cl.cl_meta <- (Meta.NativeGeneric, [], cl.cl_pos) :: cl.cl_meta;
-									Some true
-								| _ ->
-									(* if it is, loop through all fields + statics and look for non-hxgeneric
-										generic classes that have KTypeParameter as params *)
-									let raise_or_return_true = if raise_if_native then
-											(fun cf -> raise (Cannot_be_native(path, raise_pos, iface_path, ReasonField(cf.cf_name, cf.cf_type))))
-										else
-											(fun cf -> true)
-									in
-									let rec cfs_must_be_native cfs =
-										match cfs with
-											| [] -> false
-											| cf :: cfs when Type.is_physical_field cf ->
-												let t = follow (gen.greal_type cf.cf_type) in
-												(match t with
-													| TInst( { cl_kind = KTypeParameter _ }, _ ) -> cfs_must_be_native cfs
-													| TInst(cl,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TClassDecl cl)) ->
-														if not (Hashtbl.mem gen.gtparam_cast cl.cl_path) then raise_or_return_true cf else cfs_must_be_native cfs
-													| TEnum(e,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TEnumDecl e)) ->
-														if not (Hashtbl.mem gen.gtparam_cast e.e_path) then raise_or_return_true cf else cfs_must_be_native cfs
-													| _ -> cfs_must_be_native cfs (* TAbstracts / Dynamics can't be generic *)
-												)
-											| _ :: cfs ->
-												cfs_must_be_native cfs
-									in
-									if cfs_must_be_native cl.cl_ordered_fields then begin
-										cl.cl_meta <- (Meta.NativeGeneric, [], cl.cl_pos) :: cl.cl_meta;
-										Some false
-									end else if isfirst && !has_unresolved then
-										None
-									else begin
-										cl.cl_meta <- (Meta.HaxeGeneric, [], cl.cl_pos) :: cl.cl_meta;
-										Some true
-									end
-				end
-			| TEnumDecl e ->
-				if Meta.has Meta.NativeGeneric e.e_meta then begin
-					if raise_if_native then raise (Cannot_be_native(path, raise_pos, iface_path, ReasonExplicit));
-					Some false
-				end else if Meta.has Meta.HaxeGeneric e.e_meta then
-					Some true
-				else if not (is_hxgen (TEnumDecl e)) then begin
-					e.e_meta <- (Meta.NativeGeneric, [], e.e_pos) :: e.e_meta;
-					Some false
-				end else begin
-					(* if enum is not generic, then it's hxgeneric *)
-					match e.e_params with
-						| [] ->
-							e.e_meta <- (Meta.HaxeGeneric, [], e.e_pos) :: e.e_meta;
-							Some true
-						| _ ->
-							let raise_or_return_true = if raise_if_native then
-									(fun name t -> raise (Cannot_be_native(path, raise_pos, iface_path, ReasonField(name, t))))
-								else
-									(fun _ _ -> true)
-							in
-							let rec efs_must_be_native efs =
-								match efs with
-									| [] -> false
-									| ef :: efs ->
-										let t = follow (gen.greal_type ef.ef_type) in
-										match t with
-											| TFun(args, _) ->
-												if List.exists (fun (n,o,t) ->
-													let t = follow t in
-													match t with
-														| TInst( { cl_kind = KTypeParameter _ }, _ ) ->
-															false
-														| TInst(cl,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TClassDecl cl)) ->
-															if not (Hashtbl.mem gen.gtparam_cast cl.cl_path) then raise_or_return_true ef.ef_name t else false
-														| TEnum(e,p) when has_type_params t && is_false (set_hxgeneric gen mds isfirst (TEnumDecl e)) ->
-															if not (Hashtbl.mem gen.gtparam_cast e.e_path) then raise_or_return_true ef.ef_name t else false
-														| _ -> false
-												) args then
-													true
-												else
-													efs_must_be_native efs
-											| _ -> efs_must_be_native efs
-							in
-							let efs = PMap.fold (fun ef acc -> ef :: acc) e.e_constrs [] in
-							if efs_must_be_native efs then begin
-								e.e_meta <- (Meta.NativeGeneric, [], e.e_pos) :: e.e_meta;
-								Some false
-							end else if isfirst && !has_unresolved then
-								None
-							else begin
-								e.e_meta <- (Meta.HaxeGeneric, [], e.e_pos) :: e.e_meta;
-								Some true
-							end
-				end
-			| _ -> Globals.die "" __LOC__
-	end
-
-let path_s = function
-	| [],name -> name
-	| pack,name -> String.concat "." pack ^ "." ^ name
-
-let set_hxgeneric gen md =
-	try
-		let ret = match md with
-			| TClassDecl { cl_kind = KAbstractImpl a } -> (match follow_all_md md with
-				| (TInst _ | TEnum _ as t) -> (
-					let md = match t with
-						| TInst(cl,_) -> TClassDecl cl
-						| TEnum(e,_) -> TEnumDecl e
-						| _ -> Globals.die "" __LOC__
-					in
-					let ret = set_hxgeneric gen [] true md in
-					if ret = None then get (set_hxgeneric gen [] false md) else get ret)
-				| TAbstract(a,_) -> true
-				| _ -> true)
-			| _ -> match set_hxgeneric gen [] true md with
-				| None ->
-					get (set_hxgeneric gen [] false md)
-				| Some v ->
-					v
-		in
-		if not ret then begin
-			match md with
-			| TClassDecl c ->
-				let set_hxgeneric tp = match follow tp.ttp_type with
-					| TInst(c,_) ->
-						c.cl_meta <- (Meta.NativeGeneric, [], c.cl_pos) :: c.cl_meta
-					| _ -> ()
-				in
-				List.iter set_hxgeneric c.cl_params;
-				let rec handle_field cf =
-					List.iter set_hxgeneric cf.cf_params;
-					List.iter handle_field cf.cf_overloads
-				in
-				(match c.cl_kind with
-					| KAbstractImpl a ->
-						List.iter set_hxgeneric a.a_params;
-					| _ -> ());
-				List.iter handle_field c.cl_ordered_fields;
-				List.iter handle_field c.cl_ordered_statics
-			| _ -> ()
-		end;
-		ret
-	with Cannot_be_native(path, pos, iface_path, reason) ->
-		let reason_start = "The class at path " ^ path_s path ^ " implements a haxe generic interface " ^ path_s iface_path
-			^ ". It however cannot be a haxe generic class "
-		in
-		let reason = reason_start ^ match reason with
-			| ReasonField (field_name, t) ->
-				"because its field " ^ field_name ^ " is of type " ^ debug_type t
-			| ReasonSuper (path) ->
-				"because it extends the type " ^ path_s path ^ " that was determined to be a native generic type"
-			| ReasonExplicit ->
-				"because it explicitly has the metadata @:nativeGeneric set"
-		in
-		gen.gcon.error (reason) pos;
-		Globals.die "" __LOC__
-
-let params_has_tparams params =
-	List.fold_left (fun acc t -> acc || has_type_params t) false params
-
-(* ******************************************* *)
-(* RealTypeParamsModf *)
-(* ******************************************* *)
-
-(*
-
-	This is the module filter of Real Type Parameters. It will traverse through all types and look for hxgeneric classes (only classes).
-	When found, a parameterless interface will be created and associated via the "ifaces" Hashtbl to the original class.
-	Also a "cast" function will be automatically generated which will handle unsafe downcasts to more specific type parameters (necessary for serialization)
-
-	dependencies:
-		Anything that may create hxgeneric classes must run before it.
-		Should run before ReflectionCFs (this dependency will be added to ReflectionCFs), so the added interfaces also get to be real IHxObject's
-
-*)
-
-module RealTypeParamsModf =
-struct
-
-	let set_only_hxgeneric gen =
-		let rec run md =
-			match md with
-				| TTypeDecl _ | TAbstractDecl _ -> md
-				| _ -> ignore (set_hxgeneric gen md); md
-		in
-		run
-
-	let name = "real_type_params_modf"
-
-	let priority = solve_deps name []
-
-	let rec get_fields gen cl params_cl params_cf acc =
-		let fields = List.fold_left (fun acc cf ->
-			match follow (gen.greal_type (gen.gfollow#run_f (cf.cf_type))) with
-				| TInst(cli, ((_ :: _) as p)) when (not (is_hxgeneric (TClassDecl cli))) && params_has_tparams p ->
-					(cf, apply_params cl.cl_params params_cl cf.cf_type, apply_params cl.cl_params params_cf cf.cf_type) :: acc
-				| TEnum(e, ((_ :: _) as p)) when not (is_hxgeneric (TEnumDecl e)) && params_has_tparams p ->
-					(cf, apply_params cl.cl_params params_cl cf.cf_type, apply_params cl.cl_params params_cf cf.cf_type) :: acc
-				| _ -> acc
-		) [] cl.cl_ordered_fields in
-		match cl.cl_super with
-			| Some(cs, tls) ->
-				get_fields gen cs (List.map (apply_params cl.cl_params params_cl) tls) (List.map (apply_params cl.cl_params params_cf) tls) (fields @ acc)
-			| None -> (fields @ acc)
-
-	let get_cast_name cl = String.concat "_" ((fst cl.cl_path) @ [snd cl.cl_path; "cast"]) (* explicitly define it *)
-
-	(* overrides all needed cast functions from super classes / interfaces to call the new cast function *)
-	let create_stub_casts gen cl cast_cfield =
-		(* go through superclasses and interfaces *)
-		let p = cl.cl_pos in
-		let this = { eexpr = TConst TThis; etype = (TInst(cl, extract_param_types cl.cl_params)); epos = p } in
-
-		let rec loop curcls params level reverse_params =
-			if (level <> 0 || (has_class_flag curcls CInterface) || (has_class_flag curcls CAbstract) ) && params <> [] && is_hxgeneric (TClassDecl curcls) then begin
-				let cparams = List.map (fun tp -> {tp with ttp_type=TInst (map_param (get_cl_t tp.ttp_type), [])}) curcls.cl_params in
-				let name = get_cast_name curcls in
-				if not (PMap.mem name cl.cl_fields) then begin
-					let reverse_params = List.map (apply_params curcls.cl_params params) reverse_params in
-					let cfield = mk_class_field name (TFun([], t_dynamic)) false cl.cl_pos (Method MethNormal) cparams in
-					let field = { eexpr = TField(this, FInstance(cl,extract_param_types cl.cl_params, cast_cfield)); etype = apply_params cast_cfield.cf_params reverse_params cast_cfield.cf_type; epos = p } in
-					let call =
-					{
-						eexpr = TCall(field, []);
-						etype = t_dynamic;
-						epos = p;
-					} in
-					let call = gen.gparam_func_call call field reverse_params [] in
-					let delay () =
-						cfield.cf_expr <-
-						Some {
-							eexpr = TFunction(
-							{
-								tf_args = [];
-								tf_type = t_dynamic;
-								tf_expr = mk_return call
-							});
-							etype = cfield.cf_type;
-							epos = p;
-						}
-					in
-					gen.gafter_filters_ended <- delay :: gen.gafter_filters_ended; (* do not let filters alter this expression content *)
-					cl.cl_ordered_fields <- cfield :: cl.cl_ordered_fields;
-					cl.cl_fields <- PMap.add cfield.cf_name cfield cl.cl_fields;
-					if level <> 0 then add_class_field_flag cfield CfOverride
-				end
-			end;
-			let get_reverse super supertl =
-				List.map (apply_params super.cl_params supertl) reverse_params
-			in
-			(match curcls.cl_super with
-			| None -> ()
-			| Some(super, supertl) ->
-				let super_params = List.map (apply_params curcls.cl_params params) supertl in
-				loop super (super_params) (level + 1) (get_reverse super super_params));
-			List.iter (fun (iface, ifacetl) ->
-				let iface_params = List.map (apply_params curcls.cl_params params) ifacetl in
-				loop iface (iface_params) level (get_reverse iface iface_params);
-			) curcls.cl_implements
-		in
-		loop cl (extract_param_types cl.cl_params) 0 (extract_param_types cl.cl_params)
-
-	(*
-		Creates a cast classfield, with the desired name
-
-		Will also look for previous cast() definitions and override them, to reflect the current type and fields
-
-		FIXME: this function still doesn't support generics that extend generics, and are cast as one of its subclasses. This needs to be taken care, by
-		looking at previous superclasses and whenever a generic class is found, its cast argument must be overridden. the toughest part is to know how to type
-		the current type correctly.
-	*)
-	let create_cast_cfield gen cl name =
-		reset_temps();
-		let basic = gen.gcon.basic in
-		let cparams = List.map (fun tp -> {tp with ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) cl.cl_params in
-		let cfield = mk_class_field name (TFun([], t_dynamic)) false cl.cl_pos (Method MethNormal) cparams in
-		let params = extract_param_types cparams in
-
-		let fields = get_fields gen cl (extract_param_types cl.cl_params) params [] in
-		let fields = List.filter (fun (cf,_,_) -> Type.is_physical_field cf) fields in
-
-		(* now create the contents of the function *)
-		(*
-			it will look something like:
-			if (typeof(T) == typeof(T2)) return this;
-
-			var new_me = new CurrentClass<T2>(EmptyInstnace);
-
-			for (field in Reflect.fields(this))
-			{
-				switch(field)
-				{
-					case "aNativeArray":
-						var newArray = new NativeArray(this.aNativeArray.Length);
-
-					default:
-						Reflect.setField(new_me, field, Reflect.field(this, field));
-				}
-			}
-		*)
-		let pos = cl.cl_pos in
-
-		let new_me_var = alloc_var "new_me" (TInst (cl, params)) in
-		let local_new_me = mk_local new_me_var pos in
-		let this = mk (TConst TThis) (TInst (cl, extract_param_types cl.cl_params)) pos in
-		let field_var = alloc_var "field" basic.tstring in
-		let local_field = mk_local field_var pos in
-		let i_var = alloc_var "i" basic.tint in
-		let local_i = mk_local i_var pos in
-		let incr_i = mk (TUnop (Increment, Postfix, local_i)) basic.tint pos in
-		let fields_var = alloc_var "fields" (basic.tarray basic.tstring) in
-		let local_fields = mk_local fields_var pos in
-
-		let fields_to_cases fields =
-			let get_path t =
-				match follow t with
-				| TInst (cl,_) -> cl.cl_path
-				| TEnum (e,_) -> e.e_path
-				| TAbstract (a,_) -> a.a_path
-				| TMono _ | TDynamic _ -> ([], "Dynamic")
-				| _ -> Globals.die "" __LOC__
-			in
-			List.map (fun (cf, t_cl, t_cf) ->
-				let t_cf = follow (gen.greal_type t_cf) in
-				let this_field = mk (TField (this, FInstance (cl, extract_param_types cl.cl_params, cf))) t_cl pos in
-				let expr =
-					binop
-						OpAssign
-						(mk (TField (local_new_me, FInstance(cl, extract_param_types cl.cl_params, cf))) t_cf pos)
-						(try (Hashtbl.find gen.gtparam_cast (get_path t_cf)) this_field t_cf with Not_found ->
-							(* if not found tparam cast, it shouldn't be a valid hxgeneric *)
-							print_endline ("Could not find a gtparam_cast for " ^ (String.concat "." (fst (get_path t_cf)) ^ "." ^ (snd (get_path t_cf))));
-							Globals.die "" __LOC__)
-						t_cf
-						pos
-				in
-				[make_string gen.gcon.basic cf.cf_name pos], expr
-			) fields
-		in
-
-		let mk_typehandle =
-			(fun cl -> mk (TCall (mk (TIdent "__typeof__") t_dynamic pos, [make_static_this cl pos])) t_dynamic pos)
-		in
-		let mk_eq cl1 cl2 =
-			binop OpEq (mk_typehandle cl1) (mk_typehandle cl2) basic.tbool pos
-		in
-		let rec mk_typehandle_cond thisparams cfparams =
-			match thisparams, cfparams with
-			| TInst (cl_this,[]) :: [], TInst (cl_cf,[]) :: [] ->
-				mk_eq cl_this cl_cf
-			| TInst (cl_this,[]) :: hd, TInst (cl_cf,[]) :: hd2 ->
-				binop OpBoolAnd (mk_eq cl_this cl_cf) (mk_typehandle_cond hd hd2) basic.tbool pos
-			| v :: hd, v2 :: hd2 ->
-				(match follow v, follow v2 with
-				| (TInst(cl1,[]) as v), (TInst(cl2,[]) as v2) ->
-					mk_typehandle_cond (v :: hd) (v2 :: hd2)
-				| _ ->
-					Globals.die "" __LOC__)
-			| _ -> Globals.die "" __LOC__
-		in
-		let fn = {
-			tf_args = [];
-			tf_type = t_dynamic;
-			tf_expr = mk (TBlock [
-				(* if (typeof(T) == typeof(T2)) return this *)
-				mk (TIf (mk_typehandle_cond (extract_param_types cl.cl_params) params, mk_return this, None)) basic.tvoid pos;
-				(* var new_me = /*special create empty with tparams construct*/ *)
-				mk (TVar (new_me_var, Some (gen.gtools.r_create_empty cl params pos))) basic.tvoid pos;
-				(* var fields = Reflect.fields(this); *)
-				mk (TVar (fields_var, Some (gen.gtools.r_fields true this))) basic.tvoid pos;
-				(* var i = 0; *)
-				mk (TVar (i_var, Some (make_int gen.gcon.basic 0 pos))) basic.tvoid pos;
-				(* while (i < fields.length) *)
-				mk (TWhile (
-					binop OpLt local_i (mk_field_access gen local_fields "length" pos) basic.tbool pos,
-					mk (TBlock [
-						(* var field = fields[i++]; *)
-						mk (TVar (field_var, Some (mk (TArray (local_fields, incr_i)) basic.tstring pos))) basic.tvoid pos;
-						(
-							(* default: Reflect.setField(new_me, field, Reflect.field(this, field)) *)
-							let edef = gen.gtools.r_set_field basic.tvoid local_new_me local_field (gen.gtools.r_field false basic.tvoid this local_field) in
-							if fields <> [] then
-								(* switch(field) { ... } *)
-								mk (TSwitch (local_field, fields_to_cases fields, Some edef)) basic.tvoid pos
-							else
-								edef;
-						)
-					]) basic.tvoid pos,
-					NormalWhile
-				)) basic.tvoid pos;
-				(* return new_me *)
-				mk_return local_new_me
-			]) t_dynamic pos
-		}
-		in
-		cfield.cf_expr <- Some (mk (TFunction fn) cfield.cf_type pos);
-		cfield
-
-	let create_static_cast_cf gen iface cf =
-		let p = iface.cl_pos in
-		let basic = gen.gcon.basic in
-		let cparams = List.map (fun tp -> {tp with ttp_name = "To_" ^ tp.ttp_name;ttp_type = TInst (map_param (get_cl_t tp.ttp_type), [])}) cf.cf_params in
-		let me_type = TInst(iface,[]) in
-		let cfield = mk_class_field ~static:true "__hx_cast" (TFun(["me",false,me_type], t_dynamic)) false iface.cl_pos (Method MethNormal) (cparams) in
-		let params = extract_param_types cparams in
-
-		let me = alloc_var "me" me_type in
-		let field = { eexpr = TField(mk_local me p, FInstance(iface, extract_param_types iface.cl_params, cf)); etype = apply_params cf.cf_params params cf.cf_type; epos = p } in
-		let call =
-		{
-			eexpr = TCall(field, []);
-			etype = t_dynamic;
-			epos = p;
-		} in
-		let call = gen.gparam_func_call call field params [] in
-
-		(* since object.someCall<ExplicitParameterDefinition>() isn't allowed on Haxe, we need to directly apply the params and delay this call *)
-		let delay () =
-			cfield.cf_expr <-
-			Some {
-				eexpr = TFunction(
-				{
-					tf_args = [me,None];
-					tf_type = t_dynamic;
-					tf_expr = mk_return {
-						eexpr = TIf(
-							{ eexpr = TBinop(Ast.OpNotEq, mk_local me p, null me.v_type p); etype = basic.tbool; epos = p },
-							call,
-							Some( null me.v_type p )
-						);
-						etype = t_dynamic;
-						epos = p;
-					}
-				});
-				etype = cfield.cf_type;
-				epos = p;
-			}
-		in
-		cfield, delay
-
-	let default_implementation gen ifaces base_generic =
-		let add_iface cl =
-			gen.gadd_to_module (TClassDecl cl) (max_dep);
-		in
-
-		let implement_stub_cast cthis iface tl =
-			let name = get_cast_name iface in
-			if not (PMap.mem name cthis.cl_fields) then begin
-				let cparams = List.map (fun tp -> {tp with ttp_name = "To_" ^ tp.ttp_name;ttp_type = TInst(map_param (get_cl_t tp.ttp_type), [])}) iface.cl_params in
-				let field = mk_class_field name (TFun([],t_dynamic)) false iface.cl_pos (Method MethNormal) cparams in
-				let this = { eexpr = TConst TThis; etype = TInst(cthis, extract_param_types cthis.cl_params); epos = cthis.cl_pos } in
-				field.cf_expr <- Some {
-					etype = TFun([],t_dynamic);
-					epos = this.epos;
-					eexpr = TFunction {
-						tf_type = t_dynamic;
-						tf_args = [];
-						tf_expr = mk_block (mk_return this)
-					}
-				};
-				cthis.cl_ordered_fields <- field :: cthis.cl_ordered_fields;
-				cthis.cl_fields <- PMap.add name field cthis.cl_fields
-			end
-		in
-
-		let rec run md =
-			match md with
-				| TClassDecl ({ cl_params = [] } as cl) ->
-					(* see if we're implementing any generic interface *)
-					let rec check (iface,tl) =
-						if tl <> [] && set_hxgeneric gen (TClassDecl iface) then
-							(* implement cast stub *)
-							implement_stub_cast cl iface tl;
-						List.iter (fun (s,stl) -> check (s, List.map (apply_params iface.cl_params tl) stl)) iface.cl_implements;
-					in
-					List.iter (check) cl.cl_implements;
-					md
-				| TClassDecl ({ cl_params = hd :: tl } as cl) when set_hxgeneric gen md ->
-					let iface = mk_class cl.cl_module cl.cl_path cl.cl_pos in
-					iface.cl_array_access <- Option.map (apply_params (cl.cl_params) (List.map (fun _ -> t_dynamic) cl.cl_params)) cl.cl_array_access;
-					if (has_class_flag cl CExtern) then add_class_flag iface CExtern;
-					iface.cl_module <- cl.cl_module;
-					iface.cl_private <- cl.cl_private;
-					iface.cl_meta <-
-						(Meta.HxGen, [], cl.cl_pos)
-						::
-						(Meta.Custom "generic_iface", [(EConst(Int(string_of_int(List.length cl.cl_params), None)), cl.cl_pos)], cl.cl_pos)
-						::
-						iface.cl_meta;
-					Hashtbl.add ifaces cl.cl_path iface;
-
-					iface.cl_implements <- (base_generic, []) :: iface.cl_implements;
-					add_class_flag iface CInterface;
-					cl.cl_implements <- (iface, []) :: cl.cl_implements;
-
-					let name = get_cast_name cl in
-					let cast_cf = create_cast_cfield gen cl name in
-					if not (has_class_flag cl CInterface) then create_stub_casts gen cl cast_cf;
-
-					let rec loop c = match c.cl_super with
-						| None -> ()
-						| Some(sup,_) -> try
-							let siface = Hashtbl.find ifaces sup.cl_path in
-							iface.cl_implements <- (siface,[]) :: iface.cl_implements;
-							()
-						with | Not_found -> loop sup
-					in
-					loop cl;
-
-					(if not (has_class_flag cl CInterface) && not (has_class_flag cl CAbstract) then cl.cl_ordered_fields <- cast_cf :: cl.cl_ordered_fields);
-					let iface_cf = mk_class_field name cast_cf.cf_type false cast_cf.cf_pos (Method MethNormal) cast_cf.cf_params in
-					let cast_static_cf, delay = create_static_cast_cf gen iface iface_cf in
-
-					cl.cl_ordered_statics <- cast_static_cf :: cl.cl_ordered_statics;
-					cl.cl_statics <- PMap.add cast_static_cf.cf_name cast_static_cf cl.cl_statics;
-					gen.gafter_filters_ended <- delay :: gen.gafter_filters_ended; (* do not let filters alter this expression content *)
-
-					iface_cf.cf_type <- cast_cf.cf_type;
-					iface.cl_fields <- PMap.add name iface_cf iface.cl_fields;
-					let fields = List.filter (fun cf -> match cf.cf_kind with
-						| Var _ | Method MethDynamic -> false
-						| Method _ when has_class_field_flag cf CfAbstract -> false
-						| _ ->
-							let is_override = has_class_field_flag cf CfOverride in
-							let cf_type = if is_override && not (has_class_field_flag cf CfOverload) then
-								match find_first_declared_field gen cl cf.cf_name with
-									| Some(_,_,declared_t,_,_,_,_) -> declared_t
-									| _ -> Globals.die "" __LOC__
-							else
-								cf.cf_type
-							in
-
-							not (has_type_params cf_type)
-						) cl.cl_ordered_fields
-					in
-					let fields = List.map (fun f -> mk_class_field f.cf_name f.cf_type (has_class_field_flag f CfPublic) f.cf_pos f.cf_kind f.cf_params) fields in
-					let fields = if has_class_flag cl CAbstract then fields else iface_cf :: fields in
-					iface.cl_ordered_fields <- fields;
-					List.iter (fun f -> iface.cl_fields <- PMap.add f.cf_name f iface.cl_fields) fields;
-
-					add_iface iface;
-					md
-				| TTypeDecl _ | TAbstractDecl _ -> md
-				| TEnumDecl _ ->
-					ignore (set_hxgeneric gen md);
-					md
-				| _ -> ignore (set_hxgeneric gen md); md
-		in
-		run
-
-	let configure gen mapping_func =
-		gen.gmodule_filters#add name (PCustom priority) mapping_func
-
-end;;
-
-(* create a common interface without type parameters and only a __Cast<> function *)
-let default_implementation gen (dyn_tparam_cast:texpr->t->texpr) ifaces =
-	let change_expr e cl iface params =
-		let field = mk_static_field_access_infer cl "__hx_cast" e.epos params in
-		let elist = [mk_cast (TInst(iface,[])) e] in
-		let call = { eexpr = TCall(field, elist); etype = t_dynamic; epos = e.epos } in
-
-		gen.gparam_func_call call field params elist
-	in
-
-	let rec run e =
-		match e.eexpr with
-				| TCast(cast_expr, _) ->
-					(* see if casting to a native generic class *)
-					let t = gen.greal_type e.etype in
-					let unifies =
-						let ctype = gen.greal_type cast_expr.etype in
-						match follow ctype with
-						| TInst(cl,_) -> (try
-							unify ctype t;
-							true
-						with | Unify_error el ->
-							false)
-						| _ -> false
-					in
-					let unifies = unifies && not (Common.raw_defined gen.gcon "cs_safe_casts") in
-					(match follow t with
-						| TInst(cl, p1 :: pl) when is_hxgeneric (TClassDecl cl) && not unifies && not (Meta.has Meta.Enum cl.cl_meta) ->
-							let iface = Hashtbl.find ifaces cl.cl_path in
-							mk_cast e.etype (change_expr (Type.map_expr run cast_expr) cl iface (p1 :: pl))
-						| _ -> Type.map_expr run e
-					)
-				| _ -> Type.map_expr run e
-	in
-	run
-
-let configure gen (dyn_tparam_cast:texpr->t->texpr) ifaces base_generic =
-	gen.ghas_tparam_cast_handler <- true;
-	let traverse = default_implementation gen dyn_tparam_cast ifaces in
-	gen.gsyntax_filters#add name (PCustom priority) traverse;
-	RealTypeParamsModf.configure gen (RealTypeParamsModf.default_implementation gen ifaces base_generic)

+ 0 - 1536
src/codegen/gencommon/reflectionCFs.ml

@@ -1,1536 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Option
-open Common
-open Ast
-open Type
-open Codegen
-open Texpr.Builder
-open Gencommon
-open ClosuresToClass
-
-(* ******************************************* *)
-(* Reflection-enabling Class fields *)
-(* ******************************************* *)
-(*
-	This is the most hardcore codegen part of the code. There's much to improve so this code can be more readable, but at least it's running correctly right now! This will be improved. (TODO)
-
-	This module will create class fields that enable reflection for targets that have a slow or inexistent reflection abilities. Because of the similarity
-	of strategies between what should have been different modules, they are all unified in this reflection-enabling class fields.
-
-	They include:
-		* Get(throwErrors, isCheck) / Set fields . Remember to allow implements Dynamic also.
-		* Invoke fields() -> You need to configure how many invoke_field fields there will be. + invokeDynamic
-		* Has field -> parameter in get field that returns __undefined__ if it doesn't exist.
-
-		* GetType -> return the current Class<> / Enum<>
-		* Fields() -> returns all the fields / static fields. Remember to allow implements Dynamic also
-
-		* Create(arguments array), CreateEmpty - calls new() or create empty
-		* getInstanceFields / getClassFields -> show even function fields, everything!
-
-		* deleteField -> only for implements Dynamic
-
-		for enums:
-		* createEnum -> invokeField for classes
-		* createEnumIndex -> use invokeField as well, and use numbers e.g. "0", "1", "2" .... For this, use "@:alias" metadata
-		* getEnumConstructs -> fields()
-
-		need to be solved outside:
-		* getEnumName
-		* enumIndex
-		*
-
-		need to be solved by haxe code:
-		* enumParameters -> for (field in Reflect.fields(enum)) arr.push(Reflect.field(enum, field))
-
-	Standard:
-		if a class contains a @:$enum metadata, it's treated as a converted enum to class
-
-
-	Optimizations:
-		* if optimize is true, all fields will be hashed by the same hashing function as neko (31 bits int : always positive). Every function that expects a string for the field will expect also an int, for the hash
-			a string (which is nullable for compile-time hashes) + an int.
-			At compile-time, a collision will throw an error (like neko).
-			At runtime, a collision will make a negative int. Negative ints will always resolve to a special Hash<> field which takes a string.
-		* if optimize is true, Reflect.field/setField will be replaced by either the runtime version (with already hashed string), either by the own .Field()/.SetField() HxObject's version,
-			if the type is detected to already be hxgen
-		* TODO: if for() optimization for arrays is disabled, we can replace for(field in Reflect.fields(obj)) to:
-			for (field in ( (Std.is(obj, HxObject) ? ((HxObject)obj).Fields() : Reflect.fields(obj)) )) // no array copying . for further optimization this could be guaranteed to return
-			the already hashed fields.
-
-	Mappings:
-		* if create Dynamic class is true, TObjectDecl will be mapped to new DynamicClass(fields, [hashedFields], values)
-		*
-
-	dependencies:
-		There is no big dependency from this target. Though it should be a syntax filter, mainly one of the first so most expression generation has already been done,
-		while the AST has its meaning close to haxe's.
-		Should run before InitFunction so it detects variables containing expressions as "always-execute" expressions, even when using CreateEmpty
-
-		* Must run before switch() syntax changes
-
-*)
-let name = "reflection_cfs"
-
-type rcf_hash_conflict_ctx = {
-	t : t;
-	add_names : texpr->texpr->texpr;
-	get_conflict : texpr->texpr->texpr->texpr;
-	set : texpr->texpr->texpr->texpr->texpr;
-	delete : texpr->texpr->texpr->texpr;
-}
-
-type rcf_ctx =
-{
-	rcf_gen : generator_ctx;
-	rcf_ft : ClosuresToClass.closures_ctx;
-	rcf_optimize : bool;
-
-	rcf_object_iface : tclass;
-	rcf_dynamic_data_class : tclass option;
-
-	rcf_max_func_arity : int;
-
-	(*
-		the hash lookup function. can be an inlined expr or simply a function call.
-		its only needed features is that it should return the index of the key if found, and the
-		complement of the index of where it should be inserted if not found (Ints).
-
-		hash->hash_array->length->returning expression
-	*)
-	rcf_hash_function : texpr->texpr->texpr->texpr;
-
-	rcf_lookup_function : texpr->texpr;
-
-	(* hash_array->length->pos->value *)
-	rcf_insert_function : texpr->texpr->texpr->texpr->texpr;
-
-	(* hash_array->length->pos->value *)
-	rcf_remove_function : texpr->texpr->texpr->texpr;
-
-	rcf_hash_fields : (int, string) Hashtbl.t;
-
-	rcf_hash_paths : (Globals.path * int, string) Hashtbl.t;
-
-	rcf_hash_conflict_ctx : rcf_hash_conflict_ctx option;
-
-	rcf_mk_exception : string -> pos -> texpr;
-
-	(*
-		main expr -> field expr -> field string -> possible hash int (if optimize) -> possible set expr -> should_throw_exceptions -> changed expression
-
-		Changes a get / set field to the runtime resolution function
-	*)
-	rcf_on_getset_field : texpr->texpr->string->int32 option->texpr option->bool->texpr;
-
-	rcf_on_call_field : texpr->texpr->string->int32 option->texpr list->texpr;
-}
-
-let new_ctx gen ft object_iface ?dynamic_data_class optimize dynamic_getset_field dynamic_call_field hash_function lookup_function insert_function remove_function hash_conflict_ctx rcf_mk_exception =
-	{
-		rcf_gen = gen;
-		rcf_ft = ft;
-
-		rcf_optimize = optimize;
-		rcf_dynamic_data_class = dynamic_data_class;
-
-		rcf_object_iface = object_iface;
-
-		rcf_max_func_arity = 10;
-
-		rcf_hash_function = hash_function;
-		rcf_lookup_function = lookup_function;
-
-		rcf_insert_function = insert_function;
-		rcf_remove_function = remove_function;
-
-		rcf_hash_fields = Hashtbl.create 100;
-		rcf_hash_paths = Hashtbl.create 100;
-
-		rcf_on_getset_field = dynamic_getset_field;
-		rcf_on_call_field = dynamic_call_field;
-		rcf_hash_conflict_ctx = hash_conflict_ctx;
-		rcf_mk_exception = rcf_mk_exception;
-	}
-
-(*
-	methods as a bool option is a little laziness of my part.
-		None means that methods are included with normal fields;
-		Some(true) means collect only methods
-		Some(false) means collect only fields (and MethDynamic fields)
-*)
-let collect_fields cl (methods : bool option) =
-	let collected = Hashtbl.create 0 in
-	let collect cf acc =
-		if Meta.has Meta.CompilerGenerated cf.cf_meta || Meta.has Meta.SkipReflection cf.cf_meta then
-			acc
-		else match methods, cf.cf_kind with
-			| None, _ when not (Hashtbl.mem collected cf.cf_name) -> Hashtbl.add collected cf.cf_name true; ([cf.cf_name], cf) :: acc
-			| Some true, Method MethDynamic -> acc
-			| Some true, Method _ when not (Hashtbl.mem collected cf.cf_name) -> Hashtbl.add collected cf.cf_name true; ([cf.cf_name], cf) :: acc
-			| Some false, Method MethDynamic
-			| Some false, Var _ when not (Hashtbl.mem collected cf.cf_name) -> Hashtbl.add collected cf.cf_name true; ([cf.cf_name], cf) :: acc
-			| _ -> acc
-	in
-	let collect_cfs cfs acc =
-		let rec loop cfs acc =
-			match cfs with
-				| [] -> acc
-				| hd :: tl -> loop tl (collect hd acc)
-		in
-		loop cfs acc
-	in
-	let rec loop cl acc =
-		let acc = collect_cfs cl.cl_ordered_fields acc in
-		match cl.cl_super with
-			| None -> acc
-			| Some(cl,_) ->
-				if not (is_hxgen (TClassDecl cl)) then loop cl acc else acc
-	in
-
-	loop cl []
-
-let hash_field ctx f pos =
-	let h = hash f in
-	(try
-		let f2 = Hashtbl.find ctx.rcf_hash_paths (ctx.rcf_gen.gcurrent_path, h) in
-		if f <> f2 then ctx.rcf_gen.gcon.error ("Field conflict between " ^ f ^ " and " ^ f2) pos
-	with Not_found ->
-		Hashtbl.add ctx.rcf_hash_paths (ctx.rcf_gen.gcurrent_path, h) f;
-		Hashtbl.replace ctx.rcf_hash_fields h f);
-	h
-
-(* ( tf_args, switch_var ) *)
-let field_type_args ctx pos =
-	match ctx.rcf_optimize with
-		| true ->
-			let field_name, field_hash = alloc_var "field" ctx.rcf_gen.gcon.basic.tstring, alloc_var "hash" ctx.rcf_gen.gcon.basic.tint in
-
-			[field_name, None; field_hash, None], field_hash
-		| false ->
-			let field_name = alloc_var "field" ctx.rcf_gen.gcon.basic.tstring in
-			[field_name, None], field_name
-
-let hash_field_i32 ctx pos field_name =
-	let i = hash_field ctx field_name pos in
-	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
-
-let switch_case ctx pos field_name =
-	match ctx.rcf_optimize with
-		| true ->
-			let i = hash_field_i32 ctx pos field_name in
-			mk (TConst (TInt i)) ctx.rcf_gen.gcon.basic.tint pos
-		| false ->
-			make_string ctx.rcf_gen.gcon.basic field_name pos
-
-let call_super ctx fn_args ret_t cf cl this_t pos =
-	{
-		eexpr = TCall({
-			eexpr = TField({ eexpr = TConst(TSuper); etype = this_t; epos = pos }, FInstance(cl,extract_param_types cl.cl_params,cf));
-			etype = TFun(fun_args fn_args, ret_t);
-			epos = pos;
-		}, List.map (fun (v,_) -> mk_local v pos) fn_args);
-		etype = ret_t;
-		epos = pos;
-	}
-
-
-let enumerate_dynamic_fields ctx cl when_found base_arr =
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let pos = cl.cl_pos in
-
-	let vtmp = alloc_var "i" basic.tint in
-
-	let mk_for arr len =
-		let t = if ctx.rcf_optimize then basic.tint else basic.tstring in
-		let convert_str e = if ctx.rcf_optimize then ctx.rcf_lookup_function e else e in
-		let tmpinc = { eexpr = TUnop(Ast.Increment, Ast.Postfix, mk_local vtmp pos); etype = basic.tint; epos = pos } in
-		[
-			{ eexpr = TBinop(OpAssign, mk_local vtmp pos, make_int ctx.rcf_gen.gcon.basic 0 pos); etype = basic.tint; epos = pos };
-			{
-				eexpr = TWhile (
-					{ eexpr = TBinop(Ast.OpLt, mk_local vtmp pos, len); etype = basic.tbool; epos = pos },
-					mk_block (when_found (convert_str { eexpr = TArray (arr, tmpinc); etype = t; epos = pos })),
-					Ast.NormalWhile
-				);
-				etype = basic.tvoid;
-				epos = pos
-			}
-		]
-	in
-
-	let this_t = TInst(cl, extract_param_types cl.cl_params) in
-	let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in
-	let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in
-
-	{ eexpr = TVar (vtmp,None); etype = basic.tvoid; epos = pos }
-	::
-	if ctx.rcf_optimize then
-		mk_for (mk_this (mk_internal_name "hx" "hashes") (gen.gclasses.nativearray basic.tint)) (mk_this (mk_internal_name "hx" "length") basic.tint)
-		@
-		mk_for (mk_this (mk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray basic.tint)) (mk_this (mk_internal_name "hx" "length_f") basic.tint)
-		@
-		(
-			let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
-			let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
-			[conflict_ctx.add_names ehead base_arr]
-		)
-	else
-		mk_for (mk_this (mk_internal_name "hx" "hashes") (gen.gclasses.nativearray basic.tstring)) (mk_this (mk_internal_name "hx" "length") basic.tint)
-		@
-		mk_for (mk_this (mk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray basic.tstring)) (mk_this (mk_internal_name "hx" "length_f") basic.tint)
-
-(* *********************
-		Dynamic lookup
-		*********************
-
-		This is the behavior of standard <implements Dynamic> classes. It will replace the error throwing
-		if a field doesn't exists when looking it up.
-
-		In order for it to work, an implementation for hash_function must be created.
-		hash_function is the function to be called/inlined that will allow us to lookup the hash into a sorted array of hashes.
-		A binary search or linear search algorithm may be implemented. The only need is that if not found, the NegBits of
-		the place where it should be inserted must be returned.
-*)
-let abstract_dyn_lookup_implementation ctx this field_local hash_local may_value is_float pos =
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in
-	let a_t = if ctx.rcf_optimize then basic.tint else basic.tstring in
-	let hx_hashes = mk_this (mk_internal_name "hx" "hashes") (gen.gclasses.nativearray a_t) in
-	let hx_hashes_f = mk_this (mk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray a_t) in
-	let hx_dynamics = mk_this (mk_internal_name "hx" "dynamics") (gen.gclasses.nativearray t_empty) in
-	let hx_dynamics_f = mk_this (mk_internal_name "hx" "dynamics_f") (gen.gclasses.nativearray basic.tfloat) in
-	let hx_length = mk_this (mk_internal_name "hx" "length") (basic.tint) in
-	let hx_length_f = mk_this (mk_internal_name "hx" "length_f") (basic.tint) in
-	let res = alloc_var "res" basic.tint in
-	let fst_hash, snd_hash, fst_dynamics, snd_dynamics, fst_length, snd_length =
-		if is_float then
-			hx_hashes_f, hx_hashes, hx_dynamics_f, hx_dynamics, hx_length_f, hx_length
-		else
-			hx_hashes, hx_hashes_f, hx_dynamics, hx_dynamics_f, hx_length, hx_length_f
-	in
-	let res_local = mk_local res pos in
-	let gte = {
-		eexpr = TBinop(Ast.OpGte, res_local, { eexpr = TConst(TInt(Int32.zero)); etype = basic.tint; epos = pos });
-		etype = basic.tbool;
-		epos = pos;
-	} in
-	let mk_tarray arr idx =
-		{
-			eexpr = TArray(arr, idx);
-			etype = gen.gclasses.nativearray_type arr.etype;
-			epos = pos;
-		}
-	in
-	let ret_t = if is_float then basic.tfloat else t_dynamic in
-
-	match may_value with
-		| None ->
-			(*
-				var res = lookup(this.__hx_hashes/f, hash);
-				if (res < 0)
-				{
-					res = lookup(this.__hx_hashes_f/_, hash);
-					if(res < 0)
-						return null;
-					else
-						return __hx_dynamics_f[res];
-				} else {
-					return __hx_dynamics[res];
-				}
-			*)
-			let block =
-			[
-				{ eexpr = TVar(res, Some(ctx.rcf_hash_function hash_local fst_hash fst_length)); etype = basic.tvoid; epos = pos };
-				{ eexpr = TIf(gte, mk_return (mk_tarray fst_dynamics res_local), Some({
-					eexpr = TBlock(
-					[
-						{ eexpr = TBinop(Ast.OpAssign, res_local, ctx.rcf_hash_function hash_local snd_hash snd_length); etype = basic.tint; epos = pos };
-						{ eexpr = TIf(gte, mk_return (mk_tarray snd_dynamics res_local), None); etype = ret_t; epos = pos }
-					]);
-					etype = ret_t;
-					epos = pos;
-				})); etype = ret_t; epos = pos }
-			] in
-
-			if ctx.rcf_optimize then
-				let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
-				let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
-				let vconflict = alloc_var "conflict" conflict_ctx.t in
-				let local_conflict = mk_local vconflict pos in
-				[mk (TIf (
-					mk (TBinop (OpLt, hash_local, make_int gen.gcon.basic 0 pos)) basic.tbool pos,
-					mk (TBlock [
-						mk (TVar (vconflict, Some (conflict_ctx.get_conflict ehead hash_local field_local))) basic.tvoid pos;
-						mk (TIf (
-							mk (TBinop (OpNotEq, local_conflict, mk (TConst TNull) local_conflict.etype pos)) basic.tbool pos,
-							mk_return (field local_conflict "value" t_dynamic pos),
-							None
-						)) basic.tvoid pos;
-					]) basic.tvoid pos,
-					Some (mk (TBlock block) basic.tvoid pos)
-				)) basic.tvoid pos]
-			else
-				block
-		| Some value_local ->
-			(*
-				//if is not float:
-				//if (isNumber(value_local)) return this.__hx_setField_f(field, getNumber(value_local), false(not static));
-				var res = lookup(this.__hx_hashes/f, hash);
-				if (res >= 0)
-				{
-					return __hx_dynamics/f[res] = value_local;
-				} else {
-					res = lookup(this.__hx_hashes_f/_, hash);
-					if (res >= 0)
-					{
-						__hx_dynamics_f/_.splice(res,1);
-						__hx_hashes_f/_.splice(res,1);
-					}
-				}
-
-				__hx_hashses/_f.insert(~res, hash);
-				__hx_dynamics/_f.insert(~res, value_local);
-				return value_local;
-			*)
-			let neg_res = { eexpr = TUnop(Ast.NegBits, Ast.Prefix, res_local); etype = basic.tint; epos = pos } in
-
-			let res2 = alloc_var "res2" basic.tint in
-			let res2_local = mk_local res2 pos in
-			let gte2 = {
-				eexpr = TBinop(Ast.OpGte, res2_local, { eexpr = TConst(TInt(Int32.zero)); etype = basic.tint; epos = pos });
-				etype = basic.tbool;
-				epos = pos;
-			} in
-
-			let block =
-			[
-				{ eexpr = TVar(res, Some(ctx.rcf_hash_function hash_local fst_hash fst_length)); etype = basic.tvoid; epos = pos };
-				{
-					eexpr = TIf(gte,
-						mk_return { eexpr = TBinop(Ast.OpAssign, mk_tarray fst_dynamics res_local, value_local); etype = value_local.etype; epos = pos },
-						Some({ eexpr = TBlock([
-							{ eexpr = TVar( res2, Some(ctx.rcf_hash_function hash_local snd_hash snd_length)); etype = basic.tvoid; epos = pos };
-							{
-								eexpr = TIf(gte2, { eexpr = TBlock([
-									ctx.rcf_remove_function snd_hash snd_length res2_local;
-									ctx.rcf_remove_function snd_dynamics snd_length res2_local;
-									mk (TUnop(Decrement,Postfix,snd_length)) basic.tint pos
-								]); etype = t_dynamic; epos = pos }, None);
-								etype = t_dynamic;
-								epos = pos;
-							}
-						]); etype = t_dynamic; epos = pos }));
-					etype = t_dynamic;
-					epos = pos;
-				};
-				ctx.rcf_insert_function fst_hash fst_length neg_res hash_local;
-				ctx.rcf_insert_function fst_dynamics fst_length neg_res value_local;
-				mk (TUnop(Increment,Postfix,fst_length)) basic.tint pos;
-			] in
-
-			let block =
-				if ctx.rcf_optimize then
-					let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
-					let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
-					[mk (TIf (
-						mk (TBinop (OpLt, hash_local, make_int gen.gcon.basic 0 pos)) basic.tbool pos,
-						conflict_ctx.set ehead hash_local field_local value_local,
-						Some (mk (TBlock block) basic.tvoid pos)
-					)) basic.tvoid pos]
-				else
-					block
-			in
-			block @ [mk_return value_local]
-
-let get_delete_field ctx cl is_dynamic =
-	let pos = cl.cl_pos in
-	let this_t = TInst(cl, extract_param_types cl.cl_params) in
-	let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let tf_args, switch_var = field_type_args ctx pos in
-	let local_switch_var = mk_local switch_var pos in
-	let fun_type = TFun(fun_args tf_args,basic.tbool) in
-	let cf = mk_class_field (mk_internal_name "hx" "deleteField") fun_type false pos (Method MethNormal) [] in
-	let body = if is_dynamic then begin
-		let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in
-		let a_t = if ctx.rcf_optimize then basic.tint else basic.tstring in
-		let hx_hashes = mk_this (mk_internal_name "hx" "hashes") (gen.gclasses.nativearray a_t) in
-		let hx_hashes_f = mk_this (mk_internal_name "hx" "hashes_f") (gen.gclasses.nativearray a_t) in
-		let hx_dynamics = mk_this (mk_internal_name "hx" "dynamics") (gen.gclasses.nativearray t_empty) in
-		let hx_dynamics_f = mk_this (mk_internal_name "hx" "dynamics_f") (gen.gclasses.nativearray basic.tfloat) in
-		let hx_length = mk_this (mk_internal_name "hx" "length") (basic.tint) in
-		let hx_length_f = mk_this (mk_internal_name "hx" "length_f") (basic.tint) in
-		let res = alloc_var "res" basic.tint in
-		let res_local = mk_local res pos in
-		let gte = {
-			eexpr = TBinop(Ast.OpGte, res_local, { eexpr = TConst(TInt(Int32.zero)); etype = basic.tint; epos = pos });
-			etype = basic.tbool;
-			epos = pos;
-		} in
-		(*
-			var res = lookup(this.__hx_hashes, hash);
-			if (res >= 0)
-			{
-				__hx_dynamics.splice(res,1);
-				__hx_hashes.splice(res,1);
-
-				return true;
-			} else {
-				res = lookup(this.__hx_hashes_f, hash);
-				if (res >= 0)
-				{
-					__hx_dynamics_f.splice(res,1);
-					__hx_hashes_f.splice(res,1);
-
-					return true;
-				}
-			}
-
-			return false;
-		*)
-		let common = [
-			{ eexpr = TVar(res,Some(ctx.rcf_hash_function local_switch_var hx_hashes hx_length)); etype = basic.tvoid; epos = pos };
-			{
-				eexpr = TIf(gte, { eexpr = TBlock([
-					ctx.rcf_remove_function hx_hashes hx_length res_local;
-					ctx.rcf_remove_function hx_dynamics hx_length res_local;
-					mk (TUnop(Decrement,Postfix,hx_length)) basic.tint pos;
-					mk_return { eexpr = TConst(TBool true); etype = basic.tbool; epos = pos }
-				]); etype = t_dynamic; epos = pos }, Some({ eexpr = TBlock([
-					{ eexpr = TBinop(Ast.OpAssign, res_local, ctx.rcf_hash_function local_switch_var hx_hashes_f hx_length_f); etype = basic.tint; epos = pos };
-					{ eexpr = TIf(gte, { eexpr = TBlock([
-						ctx.rcf_remove_function hx_hashes_f hx_length_f res_local;
-						ctx.rcf_remove_function hx_dynamics_f hx_length_f res_local;
-						mk (TUnop(Decrement,Postfix,hx_length_f)) basic.tint pos;
-						mk_return { eexpr = TConst(TBool true); etype = basic.tbool; epos = pos }
-					]); etype = t_dynamic; epos = pos }, None); etype = t_dynamic; epos = pos }
-				]); etype = t_dynamic; epos = pos }));
-				etype = t_dynamic;
-				epos = pos;
-			};
-			mk_return { eexpr = TConst(TBool false); etype = basic.tbool; epos = pos }
-		] in
-
-		if ctx.rcf_optimize then
-			let v_name = match tf_args with (v,_) :: _ -> v | _ -> Globals.die "" __LOC__ in
-			let local_name = mk_local v_name pos in
-			let conflict_ctx = Option.get ctx.rcf_hash_conflict_ctx in
-			let ehead = mk_this (mk_internal_name "hx" "conflicts") conflict_ctx.t in
-			(mk (TIf (
-				binop OpLt local_switch_var (make_int gen.gcon.basic 0 pos) basic.tbool pos,
-				mk_return (conflict_ctx.delete ehead local_switch_var local_name),
-				None
-			)) basic.tvoid pos) :: common
-		else
-			common
-	end else
-	[
-		mk_return { eexpr = TConst(TBool false); etype = basic.tbool; epos = pos }
-	] in
-
-	(* create function *)
-	let fn =
-	{
-		tf_args = tf_args;
-		tf_type = basic.tbool;
-		tf_expr = { eexpr = TBlock(body); etype = t_dynamic; epos = pos }
-	} in
-	cf.cf_expr <- Some({ eexpr = TFunction(fn); etype = fun_type; epos = pos });
-	cf
-
-let is_override cl = match cl.cl_super with
-	| Some (cl, _) when is_hxgen (TClassDecl cl) -> true
-	| _ -> false
-
-(* WARNING: this will only work if overloading contructors is possible on target language *)
-let implement_dynamic_object_ctor ctx cl =
-	let rec is_side_effects_free e =
-		match e.eexpr with
-			| TConst _
-			| TLocal _
-			| TFunction _
-			| TTypeExpr _ ->
-				true
-			| TNew(clnew,[],params) when clnew == cl ->
-				List.for_all is_side_effects_free params
-			| TUnop(Increment,_,_)
-			| TUnop(Decrement,_,_)
-			| TBinop(OpAssign,_,_)
-			| TBinop(OpAssignOp _,_,_) ->
-				false
-			| TUnop(_,_,e) ->
-				is_side_effects_free e
-			| TArray(e1,e2)
-			| TBinop(_,e1,e2) ->
-				is_side_effects_free e1 && is_side_effects_free e2
-			| TIf(cond,e1,Some e2) ->
-				is_side_effects_free cond && is_side_effects_free e1 && is_side_effects_free e2
-			| TField(e,_)
-			| TParenthesis e | TMeta(_,e) -> is_side_effects_free e
-			| TArrayDecl el -> List.for_all is_side_effects_free el
-			| TCast(e,_) -> is_side_effects_free e
-			| _ -> false
-	in
-
-	let pos = cl.cl_pos in
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let hasht = if ctx.rcf_optimize then basic.tint else basic.tstring in
-
-	(* and finally we will return a function that transforms a TObjectDecl into a new DynamicObject() call *)
-	let rec loop objdecl acc acc_f =
-		match objdecl with
-			| [] -> acc,acc_f
-			| (name,expr) :: tl ->
-				let real_t = gen.greal_type expr.etype in
-				match follow expr.etype with
-					| TInst ( { cl_path = ["haxe"], "Int64" }, [] ) ->
-						loop tl ((name, gen.ghandle_cast t_dynamic real_t expr) :: acc) acc_f
-					| _ ->
-						if like_float real_t && not (like_i64 real_t) then
-							loop tl acc ((name, gen.ghandle_cast basic.tfloat real_t expr) :: acc_f)
-						else
-							loop tl ((name, gen.ghandle_cast t_dynamic real_t expr) :: acc) acc_f
-	in
-
-	let may_hash_field s =
-		if ctx.rcf_optimize then begin
-			mk (TConst (TInt (hash_field_i32 ctx pos s))) basic.tint pos
-		end else begin
-			make_string gen.gcon.basic s pos
-		end
-	in
-
-	let do_objdecl e objdecl =
-		let exprs_before = ref [] in
-		let rec change_exprs decl acc = match decl with
-			| ((name,_,_),expr) :: tl ->
-				if is_side_effects_free expr then
-					change_exprs tl ((name,expr) :: acc)
-				else begin
-					let var = mk_temp "odecl" expr.etype in
-					exprs_before := { eexpr = TVar(var,Some expr); etype = basic.tvoid; epos = expr.epos } :: !exprs_before;
-					change_exprs tl ((name,mk_local var expr.epos) :: acc)
-				end
-			| [] -> acc
-		in
-		let objdecl = change_exprs objdecl [] in
-
-		let odecl, odecl_f = loop objdecl [] [] in
-		let changed_expr = List.map (fun (s,e) -> (may_hash_field s,e)) in
-		let odecl, odecl_f = changed_expr odecl, changed_expr odecl_f in
-		let sort_fn (e1,_) (e2,_) =
-			match e1.eexpr, e2.eexpr with
-				| TConst(TInt i1), TConst(TInt i2) -> compare i1 i2
-				| TConst(TString s1), TConst(TString s2) -> compare s1 s2
-				| _ -> Globals.die "" __LOC__
-		in
-
-		let odecl, odecl_f = List.sort sort_fn odecl, List.sort sort_fn odecl_f in
-		let ret = {
-			e with eexpr = TNew(cl,[],
-				[
-					mk_nativearray_decl gen hasht (List.map fst odecl) pos;
-					mk_nativearray_decl gen t_empty (List.map snd odecl) pos;
-					mk_nativearray_decl gen hasht (List.map fst odecl_f) pos;
-					mk_nativearray_decl gen basic.tfloat (List.map snd odecl_f) pos;
-				]);
-		} in
-		match !exprs_before with
-			| [] -> ret
-			| block ->
-				{
-					eexpr = TBlock(List.rev block @ [ret]);
-					etype = ret.etype;
-					epos = ret.epos;
-				}
-	in
-	do_objdecl
-
-(*
-	Implements:
-		__hx_lookupField(field:String, throwErrors:Bool, isCheck:Bool, handleProperties:Bool, isFirst:Bool):Dynamic
-
-		__hx_lookupField_f(field:String, throwErrors:Bool, handleProperties:Bool, isFirst:Bool):Float
-
-		__hx_lookupSetField(field:String, value:Dynamic, handleProperties:Bool, isFirst:Bool):Dynamic;
-
-		__hx_lookupSetField(field:String, value:Float, handleProperties:Bool, isFirst:Bool):Float;
-*)
-let implement_final_lookup ctx cl =
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let pos = cl.cl_pos in
-	let is_override = is_override cl in
-
-	(* let this = { eexpr = TConst(TThis); etype = TInst(cl, extract_param_types cl.cl_params); epos = pos } in *)
-
-	let mk_throw str pos =
-		let e = ctx.rcf_mk_exception str pos in
-		make_throw e pos
-	in
-
-	(*
-		this function will create the class fields and call callback for each version
-
-		callback : is_float fields_args switch_var throw_errors_option is_check_option value_option : texpr list
-	*)
-	let create_cfs is_dynamic callback =
-		let create_cf is_float is_set =
-			let name = mk_internal_name "hx" ( (if is_set then "lookupSetField" else "lookupField") ^ (if is_float then "_f" else "") ) in
-			let field_args, switch_var = field_type_args ctx pos in
-			let ret_t = if is_float then basic.tfloat else t_dynamic in
-			let tf_args, throw_errors_opt =
-				if is_set then
-					field_args, None
-				else
-					let v = alloc_var "throwErrors" basic.tbool in
-					field_args @ [v,None], Some v
-			in
-			let tf_args, is_check_opt =
-				if is_set || is_float then
-					tf_args, None
-				else
-					let v = alloc_var "isCheck" basic.tbool in
-					tf_args @ [v,None], Some v
-			in
-			let tf_args, value_opt =
-				if not is_set then
-					tf_args, None
-				else
-					let v = alloc_var "value" ret_t in
-					field_args @ [v,None], Some v
-			in
-
-			let fun_t = TFun(fun_args tf_args, ret_t) in
-			let cf = mk_class_field name fun_t false pos (Method MethNormal) [] in
-			let block = callback is_float field_args switch_var throw_errors_opt is_check_opt value_opt in
-			let block = if not is_set then let tl = begin
-				let throw_errors_local = mk_local (get throw_errors_opt) pos in
-				let mk_check_throw msg =
-				{
-					eexpr = TIf(throw_errors_local, mk_throw msg pos, Some (mk_return (null ret_t pos)));
-					etype = ret_t;
-					epos = pos
-				} in
-
-				let mk_may_check_throw msg = if is_dynamic then mk_return (null ret_t pos) else mk_check_throw msg in
-				if is_float then begin
-					[
-						mk_may_check_throw "Field not found or incompatible field type.";
-					]
-				end else begin
-					let is_check_local = mk_local (get is_check_opt) pos in
-					[
-						{
-							eexpr = TIf(is_check_local, mk_return (undefined pos), Some( mk_may_check_throw "Field not found." ));
-							etype = ret_t;
-							epos = pos;
-						}
-					]
-				end
-			end in block @ tl else block in
-			cf.cf_expr <- Some(
-				{
-					eexpr = TFunction({
-						tf_args = tf_args;
-						tf_type = ret_t;
-						tf_expr = { eexpr = TBlock(block); etype = ret_t; epos = pos }
-					});
-					etype = fun_t;
-					epos = pos
-				}
-			);
-			cf
-		in
-		let cfs =
-		[
-			create_cf false false;
-			create_cf true false;
-			create_cf false true;
-			create_cf true true
-		] in
-		cl.cl_ordered_fields <- cl.cl_ordered_fields @ cfs;
-		List.iter (fun cf ->
-			cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields;
-			if is_override then add_class_field_flag cf CfOverride
-		) cfs
-	in
-	if not is_override then begin
-		create_cfs false (fun is_float fields_args switch_var _ _ value_opt ->
-			match value_opt with
-			| None -> (* is not set *)
-				[]
-			| Some _ -> (* is set *)
-				if is_float then
-					[ mk_throw "Cannot access field for writing or incompatible type." pos ]
-				else
-					[ mk_throw "Cannot access field for writing." pos ]
-		)
-	end
-
-(* *)
-let implement_get_set ctx cl =
-	let gen = ctx.rcf_gen in
-	let mk_cfield is_set is_float =
-		let pos = cl.cl_pos in
-		let basic = ctx.rcf_gen.gcon.basic in
-		let tf_args, switch_var = field_type_args ctx pos in
-		let field_args = tf_args in
-		let local_switch_var = { eexpr = TLocal(switch_var); etype = switch_var.v_type; epos = pos } in
-
-		let handle_prop = alloc_var "handleProperties" basic.tbool in
-		let handle_prop_local = mk_local handle_prop pos in
-
-		let this = { eexpr = TConst TThis; etype = TInst(cl, extract_param_types cl.cl_params); epos = pos } in
-		let mk_this_call_raw name fun_t params =
-			{ eexpr = TCall( { (mk_field_access gen this name pos) with etype = fun_t; }, params ); etype = snd (get_fun fun_t); epos = pos }
-		in
-
-		let fun_type = ref (TFun([], basic.tvoid)) in
-		let fun_name = mk_internal_name "hx" ( (if is_set then "setField" else "getField") ^ (if is_float then "_f" else "") ) in
-		let cfield = mk_class_field fun_name !fun_type false pos (Method MethNormal) [] in
-
-		let maybe_cast e = e in
-
-		let t = TInst(cl, extract_param_types cl.cl_params) in
-
-		(* if it's not latest hxgen class -> check super *)
-		let mk_do_default args do_default =
-			match cl.cl_super with
-				| None -> fun () -> maybe_cast (do_default ())
-				| Some (super, sparams) when not (is_hxgen (TClassDecl super)) ->
-					fun () -> maybe_cast (do_default ())
-				| _ ->
-					fun () ->
-						mk_return {
-							eexpr = TCall(
-								{ eexpr = TField({ eexpr = TConst TSuper; etype = t; epos = pos }, FInstance(cl, extract_param_types cl.cl_params, cfield)); etype = !fun_type; epos = pos },
-								(List.map (fun (v,_) -> mk_local v pos) args) );
-							etype = if is_float then basic.tfloat else t_dynamic;
-							epos = pos;
-						};
-		in
-
-		(* if it is set function, there are some different set fields to do *)
-		let do_default, do_field, tf_args = if is_set then begin
-			let value_var = alloc_var "value" (if is_float then basic.tfloat else t_dynamic) in
-			let value_local = { eexpr = TLocal(value_var); etype = value_var.v_type; epos = pos } in
-			let tf_args = tf_args @ [value_var,None; handle_prop, None; ] in
-			let lookup_name = mk_internal_name "hx" ("lookupSetField" ^ if is_float then "_f" else "") in
-
-			let do_default =
-					fun () ->
-						mk_return (mk_this_call_raw lookup_name (TFun(fun_args (field_args @ [value_var,None]),value_var.v_type)) ( List.map (fun (v,_) -> mk_local v pos) field_args @ [ value_local ] ))
-			in
-
-			let do_field cf cf_type =
-				let get_field ethis = { eexpr = TField (ethis, FInstance(cl, extract_param_types cl.cl_params, cf)); etype = cf_type; epos = pos } in
-				let this = { eexpr = TConst(TThis); etype = t; epos = pos } in
-				let value_local = if is_float then match follow cf_type with
-					| TInst({ cl_kind = KTypeParameter _ }, _) ->
-						mk_cast t_dynamic value_local
-					| _ ->
-						value_local
-					else
-						value_local
-				in
-
-				let ret =
-				{
-					eexpr = TBlock([
-						{
-							eexpr = TBinop(Ast.OpAssign,
-								get_field this,
-								mk_cast cf_type value_local);
-							etype = cf_type;
-							epos = pos;
-						};
-						mk_return value_local
-					]);
-					etype = cf_type;
-					epos = pos;
-				} in
-				match cf.cf_kind with
-					| Var { v_write = AccCall } ->
-						let bl =
-						[
-							mk_this_call_raw ("set_" ^ cf.cf_name) (TFun(["value",false,cf.cf_type], cf.cf_type)) [ value_local ];
-							mk_return value_local
-						] in
-						if not (Type.is_physical_field cf) then
-							{ eexpr = TBlock bl; etype = value_local.etype; epos = pos }
-						else
-							{
-								eexpr = TIf(
-									handle_prop_local,
-									{ eexpr = TBlock bl; etype = value_local.etype; epos = pos },
-									Some ret);
-								etype = value_local.etype;
-								epos = pos;
-							}
-					| _ ->
-						ret
-			in
-
-			(mk_do_default tf_args do_default, do_field, tf_args)
-		end else begin
-			let throw_errors = alloc_var "throwErrors" basic.tbool in
-			let throw_errors_local = mk_local throw_errors pos in
-			let do_default, tf_args = if not is_float then begin
-				let is_check = alloc_var "isCheck" basic.tbool in
-				let is_check_local = mk_local is_check pos in
-
-				let tf_args = tf_args @ [ throw_errors,None; ] in
-
-				(* default: if (isCheck) return __undefined__ else if(throwErrors) throw "Field not found"; else return null; *)
-				let lookup_name = mk_internal_name "hx" "lookupField" in
-				let do_default =
-						fun () ->
-							mk_return (mk_this_call_raw lookup_name (TFun(fun_args (field_args @ [throw_errors,None;is_check,None; ]),t_dynamic)) ( List.map (fun (v,_) -> mk_local v pos) field_args @ [ throw_errors_local; is_check_local; ] ))
-				in
-
-				(do_default, tf_args @ [ is_check,None; handle_prop,None; ])
-			end else begin
-				let tf_args = tf_args @ [ throw_errors,None; ] in
-
-				let lookup_name = mk_internal_name "hx" "lookupField_f" in
-				let do_default =
-						fun () ->
-							mk_return (mk_this_call_raw lookup_name (TFun(fun_args (field_args @ [throw_errors,None; ]),basic.tfloat)) ( List.map (fun (v,_) -> mk_local v pos) field_args @ [ throw_errors_local; ] ))
-				in
-
-				(do_default, tf_args @ [ handle_prop,None; ])
-			end in
-
-			let get_field cf cf_type ethis cl name =
-				match cf.cf_kind with
-					| Var { v_read = AccCall } when not (Type.is_physical_field cf) ->
-						mk_this_call_raw ("get_" ^ cf.cf_name) (TFun(["value",false,cf.cf_type], cf.cf_type)) []
-					| Var { v_read = AccCall } ->
-						{
-							eexpr = TIf(
-								handle_prop_local,
-								mk_this_call_raw ("get_" ^ cf.cf_name) (TFun(["value",false,cf.cf_type], cf.cf_type)) [],
-								Some { eexpr = TField (ethis, FInstance(cl, extract_param_types cl.cl_params, cf)); etype = cf_type; epos = pos }
-							);
-							etype = cf_type;
-							epos = pos;
-						}
-					| Var _
-					| Method MethDynamic -> { eexpr = TField (ethis, FInstance(cl,extract_param_types cl.cl_params,cf)); etype = cf_type; epos = pos }
-					| _ ->
-							{ eexpr = TField (this, FClosure(Some (cl,extract_param_types cl.cl_params), cf)); etype = cf_type; epos = pos }
-			in
-
-			let do_field cf cf_type =
-				let this = { eexpr = TConst(TThis); etype = t; epos = pos } in
-				match is_float, follow cf_type with
-					| true, TInst( { cl_kind = KTypeParameter _ }, _ ) ->
-						mk_return (mk_cast basic.tfloat (mk_cast t_dynamic (get_field cf cf_type this cl cf.cf_name)))
-					| _ ->
-						mk_return (maybe_cast (get_field cf cf_type this cl cf.cf_name ))
-			in
-			(mk_do_default tf_args do_default, do_field, tf_args)
-		end in
-
-		let get_fields() =
-			let ret = collect_fields cl ( if is_float || is_set then Some (false) else None ) in
-			let ret = if is_set then List.filter (fun (_,cf) ->
-				match cf.cf_kind with
-				(* | Var { v_write = AccNever } -> false *)
-				| _ -> not (Meta.has Meta.ReadOnly cf.cf_meta)) ret
-			else
-				List.filter (fun (_,cf) ->
-				match cf.cf_kind with
-				(* | Var { v_read = AccNever } -> false *)
-				| _ -> true) ret in
-			if is_float then
-				List.filter (fun (_,cf) -> (* TODO: maybe really apply_params in cf.cf_type. The benefits would be limited, though *)
-					match follow (ctx.rcf_gen.greal_type (ctx.rcf_gen.gfollow#run_f cf.cf_type)) with
-						| TDynamic _ | TMono _
-						| TInst ({ cl_kind = KTypeParameter _ }, _) -> true
-						| t when like_float t && not (like_i64 t) -> true
-						| _ -> false
-				) ret
-			else
-				(* dynamic will always contain all references *)
-				ret
-		in
-
-		(* now we have do_default, do_field and tf_args *)
-		(* so create the switch expr *)
-		fun_type := TFun(List.map (fun (v,_) -> (v.v_name, false, v.v_type)) tf_args, if is_float then basic.tfloat else t_dynamic );
-		let has_fields = ref false in
-
-		let content =
-			let fields = get_fields() in
-			let fields = List.filter
-				(fun (_, cf) -> match is_set, cf.cf_kind with
-					| true, Var { v_write = AccCall } -> true
-					| false, Var { v_read = AccCall } -> true
-					| _ -> Type.is_physical_field cf && not (has_meta Meta.ReadOnly cf.cf_meta)
-				)
-				fields
-			in
-			(if fields <> [] then has_fields := true);
-			let cases = List.map (fun (names, cf) ->
-				(if names = [] then Globals.die "" __LOC__);
-				(List.map (switch_case ctx pos) names, do_field cf cf.cf_type)
-			) fields in
-			let default = Some(do_default()) in
-
-			mk_block { eexpr = TSwitch(local_switch_var, cases, default); etype = basic.tvoid; epos = pos }
-		in
-
-		let is_override = match cl.cl_super with
-			| Some (cl, _) when is_hxgen (TClassDecl cl) -> true
-			| _ -> false
-		in
-
-		if !has_fields || (not is_override) then begin
-			let func =
-			{
-				tf_args = tf_args;
-				tf_type = if is_float then basic.tfloat else t_dynamic;
-				tf_expr = content;
-			} in
-
-			let func = { eexpr = TFunction(func); etype = !fun_type; epos = pos } in
-
-			cfield.cf_type <- !fun_type;
-			cfield.cf_expr <- Some func;
-
-			cl.cl_ordered_fields <- cl.cl_ordered_fields @ [cfield];
-			cl.cl_fields <- PMap.add fun_name cfield cl.cl_fields;
-
-			(if is_override then add_class_field_flag cfield CfOverride)
-		end else ()
-	in
-	mk_cfield true true;
-	mk_cfield true false;
-	mk_cfield false false;
-	mk_cfield false true
-
-let implement_getFields ctx cl =
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let pos = cl.cl_pos in
-
-	(*
-		function __hx_getFields(baseArr:Array<String>)
-		{
-			//add all variable fields
-			//then:
-			super.__hx_getFields(baseArr);
-		}
-	*)
-	let name = mk_internal_name "hx" "getFields" in
-	let v_base_arr = alloc_var "baseArr" (basic.tarray basic.tstring) in
-	let base_arr = mk_local v_base_arr pos in
-
-	let tf_args = [(v_base_arr,None)] in
-	let t = TFun(fun_args tf_args, basic.tvoid) in
-	let cf = mk_class_field name t false pos (Method MethNormal) [] in
-
-	let e_pushfield = mk_field_access gen base_arr "push" pos in
-	let mk_push value = mk (TCall (e_pushfield, [value])) basic.tint pos in
-
-	let has_value = ref false in
-	let map_fields =
-		List.map (fun (_,cf) ->
-			match cf.cf_kind with
-				| Var _
-				| Method MethDynamic when not (has_class_field_flag cf CfOverride) ->
-					has_value := true;
-					mk_push (make_string gen.gcon.basic cf.cf_name pos)
-				| _ -> null basic.tvoid pos
-		)
-	in
-
-	(*
-		if it is first_dynamic, then we need to enumerate the dynamic fields
-	*)
-	let exprs =
-		if is_override cl then
-			let tparams = extract_param_types cl.cl_params in
-			let esuper = mk (TConst TSuper) (TInst(cl, tparams)) pos in
-			let efield = mk (TField (esuper, FInstance (cl, tparams, cf))) t pos in
-			[mk (TCall (efield, [base_arr])) basic.tvoid pos]
-		else
-			[]
-	in
-
-	let exprs = map_fields (collect_fields cl (Some false)) @ exprs in
-
-	cf.cf_expr <- Some {
-		eexpr = TFunction({
-			tf_args = tf_args;
-			tf_type = basic.tvoid;
-			tf_expr = mk (TBlock exprs) basic.tvoid pos
-		});
-		etype = t;
-		epos = pos
-	};
-
-	if !has_value || not (is_override cl) then begin
-		cl.cl_ordered_fields <- cl.cl_ordered_fields @ [cf];
-		cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields;
-		(if is_override cl then add_class_field_flag cf CfOverride)
-	end
-
-
-let implement_invokeField ctx slow_invoke cl =
-	(*
-		There are two ways to implement an haxe reflection-enabled class:
-		When we extend a non-hxgen class, and when we extend the base HxObject class.
-
-		Because of the added boiler plate we'd add every time we extend a non-hxgen class to implement a big IHxObject
-		interface, we'll handle the cases differently when implementing each interface.
-
-		At the IHxObject interface, there's only invokeDynamic(field, args[]), while at the HxObject class there are
-		the other, more optimized methods, that follow the Function class interface.
-
-		Since this will only be called by the Closure class, this conversion can be properly dealt with later.
-
-		TODO: create the faster version. By now only invokeDynamic will be implemented
-	*)
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let pos = cl.cl_pos in
-
-	let has_method = ref false in
-
-	let is_override = ref false in
-	let rec extends_hxobject cl =
-		match cl.cl_super with
-			| None -> true
-			| Some (cl,_) when is_hxgen (TClassDecl cl) -> is_override := true; extends_hxobject cl
-			| _ -> false
-	in
-
-	let field_args, switch_var = field_type_args ctx cl.cl_pos in
-	let field_args_exprs = List.map (fun (v,_) -> mk_local v pos) field_args in
-
-	let dynamic_arg = alloc_var "dynargs" (gen.gclasses.nativearray t_dynamic) in
-	let all_args = field_args @ [ dynamic_arg, None ] in
-	let fun_t = TFun(fun_args all_args, t_dynamic) in
-
-	let this_t = TInst(cl, extract_param_types cl.cl_params) in
-	let this = { eexpr = TConst(TThis); etype = this_t; epos = pos } in
-
-	let mk_this_call_raw name fun_t params =
-		{ eexpr = TCall( { (mk_field_access gen this name pos) with etype = fun_t }, params ); etype = snd (get_fun fun_t); epos = pos }
-	in
-
-	let extends_hxobject = extends_hxobject cl in
-	ignore extends_hxobject;
-
-	(* creates a invokeField of the class fields listed here *)
-	(*
-		function invokeField(field, dynargs)
-		{
-			switch(field)
-			{
-				case "a": this.a(dynargs[0], dynargs[1], dynargs[2]...);
-				default: super.invokeField //or this.getField(field).invokeDynamic(dynargs)
-			}
-		}
-	*)
-
-	let dyn_fun = mk_class_field (mk_internal_name "hx" "invokeField") fun_t false cl.cl_pos (Method MethNormal) [] in
-
-	let mk_switch_dyn cfs old =
-		let get_case (names,cf) =
-			has_method := true;
-			let i = ref 0 in
-			let dyn_arg_local = mk_local dynamic_arg pos in
-			let length_name = match ctx.rcf_gen.gcon.platform with Cs -> "Length" | _ -> "length" in
-			let dyn_arg_length = field dyn_arg_local length_name ctx.rcf_gen.gcon.basic.tint pos in
-			let cases = List.map (switch_case ctx pos) names in
-
-			let mk_this_call cf params =
-				let t = apply_params cf.cf_params (List.map (fun _ -> t_dynamic) cf.cf_params) cf.cf_type in
-				mk_this_call_raw cf.cf_name t params
-			in
-			(cases,
-				mk_return (
-					mk_this_call cf (List.map (fun (name,optional,t) ->
-						let idx = make_int ctx.rcf_gen.gcon.basic !i pos in
-						let ret = { eexpr = TArray(dyn_arg_local, idx); etype = t_dynamic; epos = pos } in
-						let ret =
-							if ExtType.is_rest t then
-								{ ret with eexpr = TUnop(Spread,Prefix,{ ret with etype = t }) }
-							else
-								ret
-						in
-						incr i;
-						if optional then
-							let condition = binop OpGt dyn_arg_length idx ctx.rcf_gen.gcon.basic.tbool pos in
-							mk (TIf (condition, ret, Some (make_null ret.etype pos))) ret.etype pos
-						else
-							ret
-					) (fst (get_fun (cf.cf_type))))
-				)
-			)
-		in
-
-		let cfs = List.filter (fun (_,cf) -> match cf.cf_kind with
-			| Method _ -> if has_class_field_flag cf CfOverride then false else true
-			| _ -> true) cfs
-		in
-
-		let cases = List.map get_case cfs in
-		let cases = match old with
-			| [] -> cases
-			| _ ->
-				let ncases = List.map (fun cf -> switch_case ctx pos cf.cf_name) old in
-				( ncases, mk_return (slow_invoke this (mk_local (fst (List.hd field_args)) pos) (mk_local dynamic_arg pos)) ) :: cases
-		in
-
-		let default = if !is_override then
-			mk_return (call_super ctx all_args t_dynamic dyn_fun cl this_t pos)
-		else (
-			let field = begin
-				let fun_name = mk_internal_name "hx" "getField" in
-				let tf_args, _ = field_type_args ctx pos in
-				let tf_args, args = fun_args tf_args, field_args_exprs in
-
-				let tf_args, args = tf_args @ ["throwErrors",false, basic.tbool],       args @ [make_bool gen.gcon.basic true pos] in
-				let tf_args, args = tf_args @ ["isCheck", false, basic.tbool],          args @ [make_bool gen.gcon.basic false pos] in
-				let tf_args, args = tf_args @ ["handleProperties", false, basic.tbool], args @ [make_bool gen.gcon.basic false pos] in
-
-				mk (TCall ({ (mk_field_access gen this fun_name pos) with etype = TFun(tf_args, t_dynamic) }, args)) t_dynamic pos
-			end in
-			let field = mk_cast (TInst(ctx.rcf_ft.func_class,[])) field in
-			mk_return {
-				eexpr = TCall(
-					mk_field_access gen field (mk_internal_name "hx" "invokeDynamic") pos,
-					[mk_local dynamic_arg pos]);
-				etype = t_dynamic;
-				epos = pos
-			} )
-		in
-
-		{
-			eexpr = TSwitch(mk_local switch_var pos, cases, Some default);
-			etype = basic.tvoid;
-			epos = pos;
-		}
-	in
-
-	let contents =
-		let nonstatics = collect_fields cl (Some true) in
-
-		let old_nonstatics = ref [] in
-
-		let nonstatics =
-			List.filter (fun (n,cf) ->
-				let is_old = not (PMap.mem cf.cf_name cl.cl_fields) || has_class_field_flag cf CfOverride in
-				(if is_old then old_nonstatics := cf :: !old_nonstatics);
-				not is_old
-			) nonstatics
-		in
-
-		mk_switch_dyn nonstatics !old_nonstatics
-	in
-
-	dyn_fun.cf_expr <- Some
-		{
-			eexpr = TFunction(
-			{
-				tf_args = all_args;
-				tf_type = t_dynamic;
-				tf_expr = mk_block contents;
-			});
-			etype = TFun(fun_args all_args, t_dynamic);
-			epos = pos;
-		};
-	if !is_override && not (!has_method) then () else begin
-		cl.cl_ordered_fields <- cl.cl_ordered_fields @ [dyn_fun];
-		cl.cl_fields <- PMap.add dyn_fun.cf_name dyn_fun cl.cl_fields;
-		(if !is_override then add_class_field_flag dyn_fun CfOverride)
-	end
-
-let implement_varargs_cl ctx cl =
-	let pos = cl.cl_pos in
-	let gen = ctx.rcf_gen in
-
-	let this_t = TInst(cl, extract_param_types cl.cl_params) in
-	let this = { eexpr = TConst(TThis); etype = this_t ; epos = pos } in
-	let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in
-
-	let invokedyn = mk_internal_name "hx" "invokeDynamic" in
-	let idyn_t = TFun([mk_internal_name "fn" "dynargs", false, gen.gclasses.nativearray t_dynamic], t_dynamic) in
-	let this_idyn = mk_this invokedyn idyn_t in
-
-	let map_fn arity ret vars api =
-
-		let rec loop i acc =
-			if i < 0 then
-				acc
-			else
-				let obj = api i t_dynamic None in
-				loop (i - 1) (obj :: acc)
-		in
-
-		let call_arg = if arity = (-1) then
-			api (-1) t_dynamic None
-		else if arity = 0 then
-			null (gen.gclasses.nativearray t_empty) pos
-		else
-			mk_nativearray_decl gen t_empty (loop (arity - 1) []) pos
-		in
-
-		let expr = {
-			eexpr = TCall(
-				this_idyn,
-				[ call_arg ]
-			);
-			etype = t_dynamic;
-			epos = pos
-		} in
-
-		let expr = if like_float ret && not (like_int ret) then mk_cast ret expr else expr in
-
-		mk_return expr
-	in
-
-	let all_cfs = List.filter (fun cf -> cf.cf_name <> "new" && cf.cf_name <> (invokedyn) && match cf.cf_kind with Method _ -> true | _ -> false) (ctx.rcf_ft.map_base_classfields cl map_fn) in
-
-	cl.cl_ordered_fields <- cl.cl_ordered_fields @ all_cfs;
-	List.iter (fun cf ->
-		cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields
-	) all_cfs;
-
-	List.iter (fun cf ->
-		add_class_field_flag cf CfOverride
-	) cl.cl_ordered_fields
-
-let implement_closure_cl ctx cl =
-	let pos = cl.cl_pos in
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-
-	let field_args, _ = field_type_args ctx pos in
-	let obj_arg = alloc_var "target" (TInst(ctx.rcf_object_iface, [])) in
-
-	let this_t = TInst(cl, extract_param_types cl.cl_params) in
-	let this = { eexpr = TConst(TThis); etype = this_t ; epos = pos } in
-	let mk_this field t = { (mk_field_access gen this field pos) with etype = t } in
-
-	let tf_args = field_args @ [obj_arg, None] in
-	let cfs, ctor_body = List.fold_left (fun (acc_cf,acc_expr) (v,_) ->
-		let cf = mk_class_field v.v_name v.v_type false pos (Var { v_read = AccNormal; v_write = AccNormal } ) [] in
-		let expr = { eexpr = TBinop(Ast.OpAssign, mk_this v.v_name v.v_type, mk_local v pos); etype = v.v_type; epos = pos } in
-		(cf :: acc_cf, expr :: acc_expr)
-	) ([], [])	tf_args in
-
-	let map_fn arity ret vars api =
-		let this_obj = mk_this "target" (TInst(ctx.rcf_object_iface, [])) in
-
-		let rec loop i acc =
-			if i < 0 then
-				acc
-			else
-				let obj = api i t_dynamic None in
-				loop (i - 1) (obj :: acc)
-		in
-
-		let call_arg = if arity = (-1) then
-			api (-1) t_dynamic None
-		else if arity = 0 then
-			null (gen.gclasses.nativearray t_empty) pos
-		else
-			mk_nativearray_decl gen t_empty  (loop (arity - 1) []) pos
-		in
-
-		let expr = {
-			eexpr = TCall(
-				mk_field_access gen this_obj (mk_internal_name "hx" "invokeField") pos,
-				(List.map (fun (v,_) -> mk_this v.v_name v.v_type) field_args) @ [ call_arg ]
-			);
-			etype = t_dynamic;
-			epos = pos
-		} in
-
-		let expr = if like_float ret && not (like_int ret) then mk_cast ret expr else expr in
-
-		mk_return expr
-	in
-
-	let all_cfs = List.filter (fun cf -> cf.cf_name <> "new" && match cf.cf_kind with Method _ -> true | _ -> false) (ctx.rcf_ft.map_base_classfields cl map_fn) in
-
-	List.iter (fun cf ->
-		add_class_field_flag cf CfOverride
-	) all_cfs;
-	let all_cfs = cfs @ all_cfs in
-
-	cl.cl_ordered_fields <- cl.cl_ordered_fields @ all_cfs;
-	List.iter (fun cf ->
-		cl.cl_fields <- PMap.add cf.cf_name cf cl.cl_fields
-	) all_cfs;
-
-	let ctor_t = TFun(fun_args tf_args, basic.tvoid) in
-	let ctor_cf = mk_class_field "new" ctor_t true pos (Method MethNormal) [] in
-	ctor_cf.cf_expr <- Some {
-		eexpr = TFunction({
-			tf_args = tf_args;
-			tf_type = basic.tvoid;
-			tf_expr = { eexpr = TBlock({
-				eexpr = TCall({ eexpr = TConst(TSuper); etype = TInst(cl,[]); epos = pos }, [make_int ctx.rcf_gen.gcon.basic (-1) pos; make_int ctx.rcf_gen.gcon.basic (-1) pos]);
-				etype = basic.tvoid;
-				epos = pos
-			} :: ctor_body); etype = basic.tvoid; epos = pos }
-		});
-		etype = ctor_t;
-		epos = pos
-	};
-
-	cl.cl_constructor <- Some ctor_cf;
-
-	let closure_fun eclosure e field is_static =
-		let f = make_string gen.gcon.basic field eclosure.epos in
-		let args = if ctx.rcf_optimize then [ f; { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else [ f ] in
-		let args = args @ [ mk_cast (TInst(ctx.rcf_object_iface, [])) e ] in
-
-		{ eclosure with eexpr = TNew(cl,[],args) }
-	in
-	closure_fun
-
-let get_closure_func ctx closure_cl =
-	let gen = ctx.rcf_gen in
-	let basic = gen.gcon.basic in
-	let closure_func eclosure e field is_static =
-		mk_cast eclosure.etype { eclosure with
-			eexpr = TNew(closure_cl, [], [
-				e;
-				make_string gen.gcon.basic field eclosure.epos
-			] @ (
-				if ctx.rcf_optimize then [ { eexpr = TConst(TInt (hash_field_i32 ctx eclosure.epos field)); etype = basic.tint; epos = eclosure.epos } ] else []
-			));
-			etype = TInst(closure_cl,[])
-		}
-	in
-	closure_func
-
-(*
-		main expr -> field expr -> field string -> possible set expr -> should_throw_exceptions -> changed expression
-
-		Changes a get / set
-	*
-	mutable rcf_on_getset_field : texpr->texpr->string->texpr option->bool->texpr;*)
-
-let configure_dynamic_field_access ctx =
-	let gen = ctx.rcf_gen in
-	let is_dynamic fexpr field =
-		match (field_access_esp gen (gen.greal_type fexpr.etype) field) with
-		| FEnumField _
-		| FClassField _ -> false
-		| _ -> true
-	in
-
-	let maybe_hash = if ctx.rcf_optimize then fun str pos -> Some (hash_field_i32 ctx pos str) else fun str pos -> None in
-	DynamicFieldAccess.configure gen is_dynamic
-		(fun expr fexpr field set is_unsafe ->
-			let hash = maybe_hash field fexpr.epos in
-			ctx.rcf_on_getset_field expr fexpr field hash set is_unsafe
-		)
-		(fun ecall fexpr field call_list ->
-			let hash = maybe_hash field fexpr.epos in
-			ctx.rcf_on_call_field ecall fexpr field hash call_list
-		);
-	()
-
-
-(* ******************************************* *)
-(* UniversalBaseClass *)
-(* ******************************************* *)
-(*
-	Sets the universal base class for hxgen types (HxObject / IHxObject)
-
-	dependencies:
-		As a rule, it should be one of the last module filters to run so any @:hxgen class created in the process
-		-Should- only run after RealTypeParams.Modf
-*)
-module UniversalBaseClass =
-struct
-	let name = "rcf_universal_base_class"
-	let priority = min_dep +. 10.
-
-	let configure gen baseclass baseinterface basedynamic =
-		let rec run md =
-			if is_hxgen md then
-				match md with
-				| TClassDecl cl when (has_class_flag cl CInterface) && cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path ->
-					cl.cl_implements <- (baseinterface, []) :: cl.cl_implements
-				| TClassDecl ({ cl_kind = KAbstractImpl _ | KModuleFields _ }) ->
-					(* don't add any base classes to abstract implementations and module field containers *)
-					()
-				| TClassDecl ({ cl_super = None } as cl) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && cl.cl_path <> basedynamic.cl_path ->
-					cl.cl_super <- Some (baseclass,[])
-				| TClassDecl ({ cl_super = Some(super,_) } as cl) when cl.cl_path <> baseclass.cl_path && cl.cl_path <> baseinterface.cl_path && not (is_hxgen (TClassDecl super)) ->
-					cl.cl_implements <- (baseinterface, []) :: cl.cl_implements
-				| _ ->
-					()
-		in
-		let map md = run md; md in
-		gen.gmodule_filters#add name (PCustom priority) map
-end;;
-
-
-(*
-	Priority: must run AFTER UniversalBaseClass
-*)
-let priority = solve_deps name [DAfter UniversalBaseClass.priority]
-
-let has_field_override cl name =
-	try
-		let cf = PMap.find name cl.cl_fields in
-		add_class_field_flag cf CfOverride;
-		true
-	with | Not_found ->
-		false
-
-let configure ctx baseinterface ~slow_invoke =
-	let run md =
-		(match md with
-		| TClassDecl cl when not (has_class_flag cl CExtern) && is_hxgen md && ( not (has_class_flag cl CInterface) || cl.cl_path = baseinterface.cl_path ) && (match cl.cl_kind with KAbstractImpl _ | KModuleFields _ -> false | _ -> true) ->
-			if is_some cl.cl_super then begin
-				ignore (has_field_override cl (mk_internal_name "hx" "setField"));
-				ignore (has_field_override cl (mk_internal_name "hx" "setField_f"));
-				ignore (has_field_override cl (mk_internal_name "hx" "getField_f"));
-			end;
-
-			if not (has_field_override cl (mk_internal_name "hx" "lookupField")) then implement_final_lookup ctx cl;
-			if not (has_field_override cl (mk_internal_name "hx" "getField")) then implement_get_set ctx cl;
-			if not (has_field_override cl (mk_internal_name "hx" "invokeField")) then implement_invokeField ctx slow_invoke cl;
-			if not (has_field_override cl (mk_internal_name "hx" "getFields")) then implement_getFields ctx cl;
-		| _ -> ());
-		md
-	in
-	ctx.rcf_gen.gmodule_filters#add name (PCustom priority) run

+ 0 - 101
src/codegen/gencommon/renameTypeParameters.ml

@@ -1,101 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Type
-
-(* ******************************************* *)
-(* Rename Type Parameters *)
-(* ******************************************* *)
-(*
-	This module should run after everything is already applied,
-	it will look for possible type parameter name clashing and change the classes names to a
-*)
-let run types =
-	let i = ref 0 in
-	let found_types = ref PMap.empty in
-	let check_type name on_changed =
-		let rec loop name =
-			incr i;
-			let changed_name = (name ^ (string_of_int !i)) in
-			if PMap.mem changed_name !found_types then loop name else changed_name
-		in
-		if PMap.mem name !found_types then begin
-			let new_name = loop name in
-			found_types := PMap.add new_name true !found_types;
-			on_changed new_name
-		end else found_types := PMap.add name true !found_types
-	in
-
-	let get_cls t =
-		match follow t with
-		| TInst(cl,_) -> cl
-		| _ -> Globals.die "" __LOC__
-	in
-
-	let iter_types tp =
-		let cls = get_cls tp.ttp_type in
-		let orig = cls.cl_path in
-		check_type (snd orig) (fun name -> cls.cl_path <- (fst orig, name))
-	in
-
-	let save_params save params =
-		List.fold_left (fun save tp ->
-			let cls = get_cls tp.ttp_type in
-			(cls.cl_path,tp.ttp_type) :: save) save params
-	in
-
-	List.iter (function
-		| TClassDecl cl ->
-			i := 0;
-
-			let save = [] in
-
-			found_types := PMap.empty;
-			let save = save_params save cl.cl_params in
-			List.iter iter_types cl.cl_params;
-			let cur_found_types = !found_types in
-			let save = ref save in
-			List.iter (fun cf ->
-				found_types := cur_found_types;
-				save := save_params !save cf.cf_params;
-				List.iter iter_types cf.cf_params
-			) (cl.cl_ordered_fields @ cl.cl_ordered_statics);
-
-			if !save <> [] then begin
-				let save = !save in
-				let res = cl.cl_restore in
-				cl.cl_restore <- (fun () ->
-					res();
-					List.iter (fun (path,t) ->
-						let cls = get_cls t in
-						cls.cl_path <- path) save
-				);
-			end
-
-		| TEnumDecl ( ({ e_params = hd :: tl }) ) ->
-			i := 0;
-			found_types := PMap.empty;
-			List.iter iter_types (hd :: tl)
-
-		| TAbstractDecl { a_params = hd :: tl } ->
-			i := 0;
-			found_types := PMap.empty;
-			List.iter iter_types (hd :: tl)
-
-		| _ -> ()
-	) types

+ 0 - 101
src/codegen/gencommon/setHXGen.ml

@@ -1,101 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Type
-
-(* ******************************************* *)
-(* set hxgen module *)
-(* ******************************************* *)
-(*
-	Goes through all module types and adds the @:hxGen or @:nativeGen meta to them.
-	Basically, everything that is extern is assumed to not be hxgen, unless meta :hxGen is set,
-	and everything that is not extern is assumed to be hxgen, unless meta :nativeGgen is set.
-*)
-
-(*
-	The only option is to run this filter eagerly, because it must be one of the first filters to run,
-	since many others depend of it.
-*)
-let run_filter com types =
-	let rec is_hxgen md =
-		match md with
-		| TClassDecl { cl_kind = KAbstractImpl a } ->
-			is_hxgen (TAbstractDecl a)
-		| TClassDecl cl ->
-			let rec is_hxgen_class (c,_) =
-				if (has_class_flag c CExtern) then begin
-					if Meta.has Meta.HxGen c.cl_meta then
-						true
-					else
-						Option.map_default (is_hxgen_class) false c.cl_super || List.exists is_hxgen_class c.cl_implements
-				end else begin
-					if Meta.has Meta.NativeChildren c.cl_meta || Meta.has Meta.NativeGen c.cl_meta || Meta.has Meta.Struct c.cl_meta then
-						Option.map_default is_hxgen_class false c.cl_super || List.exists is_hxgen_class c.cl_implements
-					else
-						let rec has_nativec (c,p) =
-							if is_hxgen_class (c,p) then
-								false
-							else if Meta.has Meta.Struct c.cl_meta then begin
-								com.error ("Struct types cannot be subclassed") c.cl_pos;
-								true
-							end else
-								(Meta.has Meta.NativeChildren c.cl_meta && not (Option.map_default is_hxgen_class false c.cl_super || List.exists is_hxgen_class c.cl_implements))
-								|| Option.map_default has_nativec false c.cl_super
-						in
-						if Option.map_default has_nativec false c.cl_super && not (List.exists is_hxgen_class c.cl_implements) then
-							false
-						else
-							true
-				end
-			in
-			is_hxgen_class (cl,[])
-		| TEnumDecl e ->
-			if e.e_extern then
-				Meta.has Meta.HxGen e.e_meta
-			else if Meta.has Meta.NativeGen e.e_meta then
-				if Meta.has Meta.FlatEnum e.e_meta then
-					false
-				else begin
-					com.error "Only flat enums may be @:nativeGen" e.e_pos;
-					true
-				end
-			else
-				true
-		| TAbstractDecl a when Meta.has Meta.CoreType a.a_meta ->
-			not (Meta.has Meta.NativeGen a.a_meta)
-		| TAbstractDecl a ->
-			(match follow a.a_this with
-			| TInst _ | TEnum _ | TAbstract _ ->
-				is_hxgen (module_type_of_type (follow a.a_this))
-			| _ ->
-				not (Meta.has Meta.NativeGen a.a_meta))
-		| TTypeDecl t -> (* TODO see when would we use this *)
-			false
-	in
-
-	let filter md =
-		let meta = if is_hxgen md then Meta.HxGen else Meta.NativeGen in
-		match md with
-		| TClassDecl cl -> cl.cl_meta <- (meta, [], cl.cl_pos) :: cl.cl_meta
-		| TEnumDecl e -> e.e_meta <- (meta, [], e.e_pos) :: e.e_meta
-		| TTypeDecl t -> t.t_meta <- (meta, [], t.t_pos) :: t.t_meta
-		| TAbstractDecl a -> a.a_meta <- (meta, [], a.a_pos) :: a.a_meta
-	in
-
-	List.iter filter types

+ 0 - 162
src/codegen/gencommon/switchToIf.ml

@@ -1,162 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Type
-open Codegen
-open Gencommon
-
-(* ******************************************* *)
-(* SwitchToIf *)
-(* ******************************************* *)
-(*
-	A syntax filter which changes switch expressions to if() else if() else if() ...
-
-	Also it handles switches on native enums (which are not converted to classes) by
-	rewriting the switch expression to what's supported directly by the targets.
-*)
-let name = "switch_to_if"
-let priority = solve_deps name []
-
-let rec simplify_expr e =
-	match e.eexpr with
-	| TParenthesis e | TMeta (_, e) -> simplify_expr e
-	| _ -> e
-
-let configure gen (should_convert:texpr->bool) =
-	let basic = gen.gcon.basic in
-	let rec run e =
-		match e.eexpr with
-		| TSwitch (cond, cases, default) when should_convert e ->
-			let cond_etype, should_cache =
-				match gen.gfollow#run_f cond.etype with
-				| TAbstract ({ a_path = [], "Null" }, [t]) ->
-					let rec take_off_nullable t =
-						match gen.gfollow#run_f t with
-						| TAbstract ({ a_path = [], "Null" }, [t]) -> take_off_nullable t
-						| _ -> t
-					in
-					take_off_nullable t, true
-				| _ ->
-					cond.etype, false
-			in
-
-			if should_cache && not (should_convert { e with eexpr = TSwitch ({ cond with etype = cond_etype }, cases, default) }) then begin
-				{ e with eexpr = TSwitch (mk_cast cond_etype (run cond), List.map (fun (cs,e) -> (List.map run cs, run e)) cases, Option.map run default) }
-			end else begin
-				let local, fst_block =
-					match cond.eexpr, should_cache with
-					| TLocal _, false ->
-						cond, []
-					| _ ->
-						let var = mk_temp "switch" cond_etype in
-						let cond = run cond in
-						let cond = if should_cache then mk_cast cond_etype cond else cond in
-						mk_local var cond.epos, [ mk (TVar (var,Some cond)) basic.tvoid cond.epos ]
-				in
-
-				let mk_eq cond =
-					mk (TBinop (Ast.OpEq, local, cond)) basic.tbool cond.epos
-				in
-
-				let rec mk_many_cond conds =
-					match conds with
-					| cond :: [] ->
-						mk_eq cond
-					| cond :: tl ->
-						mk (TBinop (Ast.OpBoolOr, mk_eq (run cond), mk_many_cond tl)) basic.tbool cond.epos
-					| [] ->
-						Globals.die "" __LOC__
-				in
-
-				let mk_many_cond conds =
-					let ret = mk_many_cond conds in
-					(*
-						this might be considered a hack. But since we're on a syntax filter and
-						the condition is guaranteed to not have run twice, we can really run the
-						expr filters again for it (to change e.g. OpEq accordingly)
-					*)
-					gen.gexpr_filters#run ret
-				in
-
-				let rec loop cases =
-					match cases with
-					| (conds, e) :: [] ->
-						mk (TIf (mk_many_cond conds, run e, Option.map run default)) e.etype e.epos
-					| (conds, e) :: tl ->
-						mk (TIf (mk_many_cond conds, run e, Some (loop tl))) e.etype e.epos
-					| [] ->
-						match default with
-						| None ->
-							raise Exit
-						| Some d ->
-							run d
-				in
-
-				try
-					{ e with eexpr = TBlock (fst_block @ [loop cases]) }
-				with Exit ->
-					{ e with eexpr = TBlock [] }
-			end
-
-		(*
-			Convert a switch on a non-class enum (e.g. native enums) to the native switch,
-			effectively chancing `switch enumIndex(e) { case 1: ...; case 2: ...; }` to
-			`switch e { case MyEnum.A: ...; case MyEnum.B: ...; }`, which is supported natively
-			by some target languages like Java and C#.
-		*)
-		| TSwitch (cond, cases, default) ->
-			begin
-				try
-					match (simplify_expr cond).eexpr with
-					| TEnumIndex enum
-					| TCall  ({ eexpr = TField (_, FStatic ({ cl_path = [],"Type" }, { cf_name = "enumIndex" })) }, [enum]) ->
-						let real_enum =
-							match enum.etype with
-							| TEnum (e, _) -> e
-							| _ -> raise Not_found
-						in
-						if Meta.has Meta.Class real_enum.e_meta then
-							raise Not_found;
-
-						let fields = Hashtbl.create (List.length real_enum.e_names) in
-						PMap.iter (fun _ ef -> Hashtbl.add fields ef.ef_index ef) real_enum.e_constrs;
-
-						let enum_expr = Texpr.Builder.make_typeexpr (TEnumDecl real_enum) e.epos in
-						let cases = List.map (fun (patterns, body) ->
-							let patterns = List.map (fun e ->
-								match e.eexpr with
-								| TConst (TInt i) ->
-									let ef = Hashtbl.find fields (Int32.to_int i) in
-									{ e with eexpr = TField (enum_expr, FEnum (real_enum, ef)); etype = TEnum (real_enum, List.map (fun _ -> t_dynamic) real_enum.e_params) }
-								| _ ->
-									raise Not_found
-							) patterns in
-							let body = run body in
-							patterns, body
-						) cases in
-						{ e with eexpr = TSwitch (enum, cases, Option.map run default) }
-					| _ ->
-						raise Not_found
-				with Not_found ->
-					Type.map_expr run e
-			end
-		| _ ->
-			Type.map_expr run e
-	in
-	gen.gsyntax_filters#add name (PCustom priority) run

+ 0 - 104
src/codegen/gencommon/tArrayTransform.ml

@@ -1,104 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Ast
-open Type
-open Gencommon
-
-(* ******************************************* *)
-(* Dynamic TArray Handling *)
-(* ******************************************* *)
-(*
-	In some languages you cannot overload the [] operator,
-	so we need to decide what is kept as TArray and what gets mapped.
-
-	depends on:
-		(syntax) must run before expression/statment normalization because it may generate complex expressions
-		(ok) must run before binop transformations because it may generate some untreated binop ops
-		(ok) must run before dynamic field access is transformed into reflection
-*)
-let name = "dyn_tarray"
-let priority = solve_deps name [DBefore DynamicOperators.priority; DBefore DynamicFieldAccess.priority]
-
-(* should change signature: tarray expr -> binop operation -> should change? *)
-let configure gen (should_change:texpr->Ast.binop option->bool) (get_fun:string) (set_fun:string) =
-	let basic = gen.gcon.basic in
-	let mk_get e e1 e2 =
-		let efield = mk_field_access gen e1 get_fun e.epos in
-		{ e with eexpr = TCall(efield, [e2]) }
-	in
-	let mk_set e e1 e2 evalue =
-		let efield = mk_field_access gen e1 set_fun e.epos in
-		{ e with eexpr = TCall(efield, [e2; evalue]) }
-	in
-	let rec run e =
-		match e.eexpr with
-			| TArray(e1, e2) ->
-				(* e1 should always be a var; no need to map there *)
-				if should_change e None then mk_get e (run e1) (run e2) else Type.map_expr run e
-			| TBinop (Ast.OpAssign, ({ eexpr = TArray(e1a,e2a) } as earray), evalue) when should_change earray (Some Ast.OpAssign) ->
-				mk_set e (run e1a) (run e2a) (run evalue)
-			| TBinop (Ast.OpAssignOp op,({ eexpr = TArray(e1a,e2a) } as earray) , evalue) when should_change earray (Some (Ast.OpAssignOp op)) ->
-				(* cache all arguments in vars so they don't get executed twice *)
-				(* let ensure_local gen block name e = *)
-				let block = ref [] in
-
-				let arr_local = ensure_local gen.gcon block "array" (run e1a) in
-				let idx_local = ensure_local gen.gcon block "index" (run e2a) in
-				block := (mk_set e arr_local idx_local ( { e with eexpr=TBinop(op, mk_get earray arr_local idx_local, run evalue) } )) :: !block;
-
-				{ e with eexpr = TBlock (List.rev !block) }
-			| TUnop(op, flag, ({ eexpr = TArray(e1a, e2a) } as earray)) ->
-				if should_change earray None && match op with | Not | Neg -> false | _ -> true then begin
-
-					let block = ref [] in
-
-					let actual_t = match op with
-						| Ast.Increment | Ast.Decrement -> (match follow earray.etype with
-							| TInst _ | TAbstract _ | TEnum _ -> earray.etype
-							| _ -> basic.tfloat)
-						| Ast.Not -> basic.tbool
-						| _ -> basic.tint
-					in
-
-					let val_v = mk_temp "arrVal" actual_t in
-					let ret_v = mk_temp "arrRet" actual_t in
-
-					let arr_local = ensure_local gen.gcon block "arr" (run e1a) in
-					let idx_local = ensure_local gen.gcon block "arrIndex" (run e2a) in
-
-					let val_local = { earray with eexpr = TLocal(val_v) } in
-					let ret_local = { earray with eexpr = TLocal(ret_v) } in
-					(* var idx = 1; var val = x._get(idx); var ret = val++; x._set(idx, val); ret; *)
-					block := { eexpr = TVar(val_v, Some(mk_get earray arr_local idx_local)); (* var val = x._get(idx) *)
-											etype = gen.gcon.basic.tvoid;
-											epos = e2a.epos
-										} :: !block;
-					block := { eexpr = TVar(ret_v, Some { e with eexpr = TUnop(op, flag, val_local) }); (* var ret = val++ *)
-											etype = gen.gcon.basic.tvoid;
-											epos = e2a.epos
-										} :: !block;
-					block := (mk_set e arr_local idx_local val_local) (*x._set(idx,val)*) :: !block;
-					block := ret_local :: !block;
-					{ e with eexpr = TBlock (List.rev !block) }
-				end else
-					Type.map_expr run e
-			| _ -> Type.map_expr run e
-	in
-	gen.gexpr_filters#add "dyn_tarray" (PCustom priority) run

+ 0 - 60
src/codegen/gencommon/unnecessaryCastsRemoval.ml

@@ -1,60 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Gencommon
-open Type
-
-(*
-	This module will take care of simplifying unnecessary casts, specially those made by the compiler
-	when inlining. Right now, it will only take care of casts used as a statement, which are always useless;
-
-	TODO: Take care of more cases, e.g. when the to and from types are the same
-
-	dependencies:
-		This must run after CastDetection, but before ExpressionUnwrap
-*)
-let rec take_off_cast run e =
-	match e.eexpr with
-	| TCast (c, _) -> take_off_cast run c
-	| _ -> run e
-
-let rec traverse e =
-	match e.eexpr with
-	| TBlock bl ->
-		let bl = List.map (take_off_cast traverse) bl in
-		{ e with eexpr = TBlock bl }
-	| TTry (block, catches) ->
-		{ e with eexpr = TTry(traverse (mk_block block), List.map (fun (v,block) -> (v, traverse (mk_block block))) catches) }
-	| TSwitch (cond,el_e_l, default) ->
-		{ e with eexpr = TSwitch(cond, List.map (fun (el,e) -> (el, traverse (mk_block e))) el_e_l, Option.map (fun e -> traverse (mk_block e)) default) }
-	| TWhile (cond,block,flag) ->
-		{e with eexpr = TWhile(cond,traverse (mk_block block), flag) }
-	| TIf (cond, eif, eelse) ->
-		{ e with eexpr = TIf(cond, traverse (mk_block eif), Option.map (fun e -> traverse (mk_block e)) eelse) }
-	| TFor (v,it,block) ->
-		{ e with eexpr = TFor(v,it, traverse (mk_block block)) }
-	| TFunction (tfunc) ->
-		{ e with eexpr = TFunction({ tfunc with tf_expr = traverse (mk_block tfunc.tf_expr) }) }
-	| _ ->
-		e (* if expression doesn't have a block, we will exit *)
-
-let name = "casts_removal"
-let priority = solve_deps name [DAfter CastDetect.priority; DBefore ExpressionUnwrap.priority]
-
-let configure gen =
-	gen.gsyntax_filters#add name (PCustom priority) traverse

+ 0 - 212
src/codegen/gencommon/unreachableCodeEliminationSynf.ml

@@ -1,212 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-*)
-open Common
-open Ast
-open Type
-open Gencommon
-
-(*
-	In some source code platforms, the code won't compile if there is Unreachable code, so this filter will take off any unreachable code.
-		If the parameter "handle_switch_break" is set to true, it will already add a "break" statement on switch cases when suitable;
-			in order to not confuse with while break, it will be a special expression __sbreak__
-		If the parameter "handle_not_final_returns" is set to true, it will also add final returns when functions are detected to be lacking of them.
-			(Will respect __fallback__ expressions)
-		If the parameter "java_mode" is set to true, some additional checks following the java unreachable specs
-			(http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21) will be added
-
-	dependencies:
-		This must run before SwitchBreakSynf (see SwitchBreakSynf dependecy value)
-		This must be the LAST syntax filter to run. It expects ExpressionUnwrap to have run correctly, since this will only work for source-code based targets
-*)
-type uexpr_kind =
-	| Normal
-	| BreaksLoop
-	| BreaksFunction
-
-let aggregate_kind e1 e2 =
-	match e1, e2 with
-		| Normal, _
-		| _, Normal -> Normal
-		| BreaksLoop, _
-		| _, BreaksLoop -> BreaksLoop
-		| BreaksFunction, BreaksFunction -> BreaksFunction
-
-let aggregate_constant op c1 c2=
-	match op, c1, c2 with
-		| OpEq, Some v1, Some v2 -> Some (TBool (v1 = v2))
-		| OpNotEq, Some v1, Some v2 -> Some (TBool (v1 <> v2))
-		| OpBoolOr, Some (TBool v1) , Some (TBool v2) -> Some (TBool (v1 || v2))
-		| OpBoolAnd, Some (TBool v1) , Some (TBool v2) -> Some (TBool (v1 && v2))
-		| OpAssign, _, Some v2 -> Some v2
-		| _ -> None
-
-let rec get_constant_expr e =
-	match e.eexpr with
-		| TConst (v) -> Some v
-		| TBinop(op, v1, v2) -> aggregate_constant op (get_constant_expr v1) (get_constant_expr v2)
-		| TParenthesis(e) | TMeta(_,e) -> get_constant_expr e
-		| _ -> None
-
-let init gen java_mode =
-	let should_warn = false in
-
-	let do_warn =
-		if should_warn then gen.gwarning WGenerator "Unreachable code" else (fun pos -> ())
-	in
-
-	let return_loop expr kind =
-		match kind with
-			| Normal | BreaksLoop -> expr, Normal
-			| _ -> expr, kind
-	in
-
-	let mk_sbreak = mk (TIdent "__sbreak__") t_dynamic in
-
-	let rec has_fallback expr = match expr.eexpr with
-		| TBlock(bl) -> (match List.rev bl with
-			| { eexpr = TIdent "__fallback__" } :: _ -> true
-			| ({ eexpr = TBlock(_) } as bl) :: _ -> has_fallback bl
-			| _ -> false)
-		| TIdent "__fallback__" -> true
-		| _ -> false
-	in
-
-	let handle_case = fun (expr,kind) ->
-		match kind with
-		| Normal when has_fallback expr -> expr
-		| Normal -> Type.concat expr (mk_sbreak expr.epos)
-		| BreaksLoop | BreaksFunction -> expr
-	in
-
-	let has_break = ref false in
-
-	let rec process_expr expr =
-		match expr.eexpr with
-			| TMeta (m,expr) ->
-				let expr,kind = process_expr expr in
-				{ expr with eexpr = TMeta (m, expr) }, kind
-			| TReturn _ | TThrow _ -> expr, BreaksFunction
-			| TContinue -> expr, BreaksLoop
-			| TBreak -> has_break := true; expr, BreaksLoop
-			| TCall( { eexpr = TIdent "__goto__" }, _ ) -> expr, BreaksLoop
-
-			| TBlock bl ->
-				let new_block = ref [] in
-				let is_unreachable = ref false in
-				let ret_kind = ref Normal in
-
-				List.iter (fun e ->
-					if !is_unreachable then
-						do_warn e.epos
-					else begin
-						let changed_e, kind = process_expr e in
-						new_block := changed_e :: !new_block;
-						match kind with
-							| BreaksLoop | BreaksFunction ->
-								ret_kind := kind;
-								is_unreachable := true
-							| _ -> ()
-					end
-				) bl;
-
-				{ expr with eexpr = TBlock(List.rev !new_block) }, !ret_kind
-			| TFunction tf ->
-				let changed, kind = process_expr tf.tf_expr in
-				let changed = if not (ExtType.is_void tf.tf_type) && kind <> BreaksFunction then
-					Type.concat changed (Texpr.Builder.mk_return (null tf.tf_type expr.epos))
-				else
-					changed
-				in
-
-				{ expr with eexpr = TFunction({ tf with tf_expr = changed }) }, Normal
-			| TFor(var, cond, block) ->
-				let last_has_break = !has_break in
-				has_break := false;
-
-				let changed_block, _ = process_expr block in
-				has_break := last_has_break;
-				let expr = { expr with eexpr = TFor(var, cond, changed_block) } in
-				return_loop expr Normal
-			| TIf(cond, eif, None) ->
-				if java_mode then
-					match get_constant_expr cond with
-						| Some (TBool true) ->
-							process_expr eif
-						| _ ->
-							{ expr with eexpr = TIf(cond, fst (process_expr eif), None) }, Normal
-				else
-					{ expr with eexpr = TIf(cond, fst (process_expr eif), None) }, Normal
-			| TIf(cond, eif, Some eelse) ->
-				let eif, eif_k = process_expr eif in
-				let eelse, eelse_k = process_expr eelse in
-				let k = aggregate_kind eif_k eelse_k in
-				{ expr with eexpr = TIf(cond, eif, Some eelse) }, k
-			| TWhile(cond, block, flag) ->
-				let last_has_break = !has_break in
-				has_break := false;
-
-				let block, k = process_expr block in
-				if java_mode then
-					match get_constant_expr cond, flag, !has_break with
-						| Some (TBool true), _, false ->
-							has_break := last_has_break;
-							{ expr with eexpr = TWhile(cond, block, flag) }, BreaksFunction
-						| Some (TBool false), NormalWhile, _ ->
-							has_break := last_has_break;
-							do_warn expr.epos;
-							null expr.etype expr.epos, Normal
-						| _ ->
-							has_break := last_has_break;
-							return_loop { expr with eexpr = TWhile(cond,block,flag) } Normal
-				else begin
-					has_break := last_has_break;
-					return_loop { expr with eexpr = TWhile(cond,block,flag) } Normal
-				end
-			| TSwitch(cond, el_e_l, None) ->
-				{ expr with eexpr = TSwitch(cond, List.map (fun (el, e) -> (el, handle_case (process_expr e))) el_e_l, None) }, Normal
-			| TSwitch(cond, el_e_l, Some def) ->
-				let def, k = process_expr def in
-				let def = handle_case (def, k) in
-				let k = ref k in
-				let ret = { expr with eexpr = TSwitch(cond, List.map (fun (el, e) ->
-					let e, ek = process_expr e in
-					k := aggregate_kind !k ek;
-					(el, handle_case (e, ek))
-				) el_e_l, Some def) } in
-				ret, !k
-			| TTry (e, catches) ->
-				let e, k = process_expr e in
-				let k = ref k in
-				let ret = { expr with eexpr = TTry(e, List.map (fun (v, e) ->
-					let e, ek = process_expr e in
-					k := aggregate_kind !k ek;
-					(v, e)
-				) catches) } in
-				ret, !k
-			| _ -> expr, Normal
-	in
-
-	let run e = fst (process_expr e) in
-	run
-
-let priority = min_dep -. 100.0
-
-let configure gen java_mode =
-	let run = init gen java_mode in
-	gen.gsyntax_filters#add "unreachable_synf" (PCustom priority) run

+ 3 - 6
src/compiler/generate.ml

@@ -78,13 +78,10 @@ let generate ctx tctx ext actx =
 			Genphp7.generate,"php"
 		| Cpp ->
 			Gencpp.generate,"cpp"
-		| Cs ->
-			Gencs.generate,"cs"
 		| Java ->
-			if Common.defined com Jvm then
-				Genjvm.generate actx.jvm_flag,"java"
-			else
-				Genjava.generate,"java"
+			Genjvm.generate actx.jvm_flag,"java"
+		| Cs ->
+			assert false
 		| Python ->
 			Genpy.generate,"python"
 		| Hl ->

+ 0 - 14
src/filters/filters.ml

@@ -759,10 +759,6 @@ let destruction tctx detail_times main locals =
 		commit_features com;
 		(if com.config.pf_reserved_type_paths <> [] then check_reserved_type_paths tctx else (fun _ -> ()));
 	] in
-	let type_filters = match com.platform with
-		| Cs -> type_filters @ [ fun t -> InterfaceProps.run t ]
-		| _ -> type_filters
-	in
 	let t = filter_timer detail_times ["type 3"] in
 	List.iter (fun t ->
 		begin match t with
@@ -968,16 +964,6 @@ let run com tctx main =
 		"Exceptions_filter",Exceptions.filter tctx;
 		"captured_vars",CapturedVars.captured_vars com;
 	] in
-	let filters =
-		match com.platform with
-		| Cs ->
-			SetHXGen.run_filter com new_types;
-			filters
-		| Java when not (Common.defined com Jvm)->
-			SetHXGen.run_filter com new_types;
-			filters
-		| _ -> filters
-	in
 	List.iter (run_expression_filters (timer_label detail_times ["expr 1"]) tctx filters) new_types;
 	(* PASS 1.5: pre-analyzer type filters *)
 	let filters =

+ 0 - 3568
src/generators/gencs.ml

@@ -1,3568 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *)
-open Extlib_leftovers
-open ReflectionCFs
-open Globals
-open Ast
-open Common
-open Type
-open Gencommon
-open Gencommon.SourceWriter
-open Codegen
-open Texpr.Builder
-open Printf
-open Option
-open ExtString
-
-type cs_native_constraint =
-	| CsStruct
-	| CsClass
-	| CsUnmanaged
-	| CsConstructible
-	| CsConstraint of string
-
-let get_constraint = function
-	| CsStruct -> "struct"
-	| CsClass -> "class"
-	| CsUnmanaged -> "unmanaged"
-	| CsConstructible -> "new()"
-	| CsConstraint s -> s
-
-let rec is_cs_basic_type t =
-	match follow t with
-		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
-		| TInst( { cl_path = (["haxe"], "Int64") }, [] )
-		| TAbstract ({ a_path = (["cs"], "Int64") },[])
-		| TAbstract ({ a_path = (["cs"], "UInt64") },[])
-		| TAbstract ({ a_path = ([], "Int") },[])
-		| TAbstract ({ a_path = ([], "Float") },[])
-		| TAbstract ({ a_path = ([], "Bool") },[]) ->
-			true
-		| TAbstract ({ a_path = (["cs"], "Pointer") },_) ->
-			false
-		| TAbstract _ when like_float t ->
-			true
-		| TAbstract(a,pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-			is_cs_basic_type (Abstract.get_underlying_type a pl)
-		| TEnum(e, _) as t when not (is_hxgen_t t) -> true
-		| TInst(cl, _) when Meta.has Meta.Struct cl.cl_meta -> true
-		| _ -> false
-
-let binops_names = List.fold_left (fun acc (op,n) -> PMap.add n op acc) PMap.empty Dotnet.cs_binops
-let unops_names = List.fold_left (fun acc (op,n) -> PMap.add n op acc) PMap.empty Dotnet.cs_unops
-
-let is_tparam t =
-	match follow t with
-		| TInst( { cl_kind = KTypeParameter _ }, [] ) -> true
-		| _ -> false
-
-let rec is_int_float gen t =
-	match follow (gen.greal_type t) with
-		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
-		| TAbstract ({ a_path = ([], "Int") },[])
-		| TAbstract ({ a_path = ([], "Float") },[]) ->
-			true
-		| TAbstract _ when like_float t && not (like_i64 t) ->
-			true
-		| TInst( { cl_path = (["haxe"; "lang"], "Null") }, [t] ) -> is_int_float gen t
-		| _ -> false
-
-let is_bool t =
-	match follow t with
-		| TAbstract ({ a_path = ([], "Bool") },[]) ->
-			true
-		| _ -> false
-
-let is_exactly_bool gen t =
-	match gen.gfollow#run_f t with
-		| TAbstract ({ a_path = ([], "Bool") },[]) ->
-			true
-		| _ -> false
-
-let is_dynamic gen t =
-	match follow (gen.greal_type t) with
-		| TDynamic _ -> true
-		| _ -> false
-
-let is_pointer gen t =
-	match follow (gen.greal_type t) with
-		| TAbstract( ( {a_path = ["cs"], "Pointer"}, _ ) )
-		| TInst( {cl_path = ["cs"], "Pointer"}, _ ) -> true
-		| _ -> false
-
-let rec is_null t =
-	match t with
-		| TInst( { cl_path = (["haxe"; "lang"], "Null") }, _ )
-		| TAbstract( { a_path = ([], "Null") }, _ ) -> true
-		| TType( t, tl ) -> is_null (apply_typedef t tl)
-		| TMono r ->
-			(match r.tm_type with
-			| Some t -> is_null t
-			| _ -> false)
-		| TLazy f ->
-			is_null (lazy_type f)
-		| _ -> false
-
-let rec get_ptr e = match e.eexpr with
-	| TParenthesis e | TMeta(_,e)
-	| TCast(e,_) -> get_ptr e
-	| TCall( { eexpr = TIdent "__ptr__" }, [ e ] ) ->
-		Some e
-	| _ -> None
-
-let parse_explicit_iface =
-	let regex = Str.regexp "\\." in
-	let parse_explicit_iface str =
-		let split = Str.split regex str in
-		let rec get_iface split pack =
-			match split with
-				| clname :: fn_name :: [] -> fn_name, (List.rev pack, clname)
-				| pack_piece :: tl -> get_iface tl (pack_piece :: pack)
-				| _ -> die "" __LOC__
-		in
-		get_iface split []
-	in parse_explicit_iface
-
-let rec change_md = function
-	| TAbstractDecl(a) when Meta.has Meta.Delegate a.a_meta && not (Meta.has Meta.CoreType a.a_meta) ->
-		change_md (t_to_md a.a_this)
-	| TClassDecl( { cl_kind = KAbstractImpl ({ a_this = TInst(impl,_) } as a) }) when Meta.has Meta.Delegate a.a_meta ->
-		TClassDecl impl
-	| TClassDecl( { cl_kind = KAbstractImpl (a) }) when Meta.has Meta.CoreType a.a_meta ->
-		TAbstractDecl a
-	| md -> md
-
-(**
-	Generates method overloads for a method with trailing optional arguments.
-	E.g. for `function method(a:Int, b:Bool = false) {...}`
-	generates `function method(a:Int) { method(a, false); }`
-*)
-let get_overloads_for_optional_args gen cl cf is_static =
-	match cf.cf_params,cf.cf_kind with
-	| [],Method (MethNormal | MethDynamic | MethInline) ->
-		(match cf.cf_expr, follow cf.cf_type with
-		| Some ({ eexpr = TFunction fn } as method_expr), TFun (args, return_type) ->
-			let type_params = extract_param_types cl.cl_params in
-			let rec collect_overloads tf_args_rev args_rev default_values_rev =
-				match tf_args_rev, args_rev with
-				| (_, Some default_value) :: rest_tf_args_rev, _ :: rest_args_rev ->
-					let field_expr =
-						let cl_type = TInst (cl,type_params) in
-						if cf.cf_name = "new" then
-							mk (TConst TThis) cl_type cf.cf_pos
-						else if is_static then
-							let class_expr =
-								mk (TTypeExpr (TClassDecl cl)) cl_type cf.cf_pos
-							in
-							mk (TField (class_expr, FStatic(cl,cf))) cf.cf_type cf.cf_pos
-						else
-							let this_expr =
-								mk (TConst TThis) cl_type cf.cf_pos
-							in
-							mk (TField (this_expr, FInstance(cl,type_params,cf))) cf.cf_type cf.cf_pos
-					in
-					let default_values_rev = default_values_rev @ [default_value] in
-					let args_exprs =
-						List.rev (
-							default_values_rev
-							@ (List.map (fun (v,_) -> mk_local v v.v_pos ) rest_tf_args_rev)
-						)
-					in
-					let call = { fn.tf_expr with eexpr = TCall (field_expr, args_exprs) } in
-					let fn_body =
-						if ExtType.is_void (follow return_type) then call
-						else { fn.tf_expr with eexpr = TReturn (Some call) }
-					in
-					let fn =
-						{ fn with tf_args = List.rev rest_tf_args_rev; tf_expr = mk_block fn_body }
-					in
-					{ cf with
-						cf_overloads = [];
-						cf_type = TFun (List.rev rest_args_rev, return_type);
-						cf_expr = Some { method_expr with eexpr = TFunction fn };
-					} :: collect_overloads rest_tf_args_rev rest_args_rev default_values_rev
-				| _ -> []
-			in
-			collect_overloads (List.rev fn.tf_args) (List.rev args) []
-		| _ -> []
-		)
-	| _ -> []
-
-(* used in c#-specific filters to skip some of them for the special haxe.lang.Runtime class *)
-let in_runtime_class gen =
-	match gen.gcurrent_class with
-	| Some { cl_path = ["haxe";"lang"],"Runtime"} -> true
-	| _ -> false
-
-(* ******************************************* *)
-(* CSharpSpecificESynf *)
-(* ******************************************* *)
-(*
-	Some CSharp-specific syntax filters that must run before ExpressionUnwrap
-
-	dependencies:
-		It must run before ExprUnwrap, as it may not return valid Expr/Statement expressions
-		It must run before ClassInstance, as it will detect expressions that need unchanged TTypeExpr
-*)
-module CSharpSpecificESynf =
-struct
-	let name = "csharp_specific_e"
-	let priority = solve_deps name [DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority]
-
-	let get_cl_from_t t =
-		match follow t with
-			| TInst(cl,_) -> cl
-			| _ -> die "" __LOC__
-
-	let get_ab_from_t t =
-		match follow t with
-			| TAbstract(ab,_) -> ab
-			| _ -> die "" __LOC__
-
-	let configure gen runtime_cl =
-		let basic = gen.gcon.basic in
-		let uint = match get_type gen ([], "UInt") with | TTypeDecl t -> TType(t, []) | TAbstractDecl a -> TAbstract(a, []) | _ -> die "" __LOC__ in
-
-		let rec run e =
-			match e.eexpr with
-				(* Std.is() *)
-				| TCall(
-						{ eexpr = TField( _, FStatic({ cl_path = ([], "Std") }, { cf_name = ("is" | "isOfType") })) },
-						[ obj; { eexpr = TTypeExpr(TClassDecl { cl_path = [], "Dynamic" } | TAbstractDecl { a_path = [], "Dynamic" }) }]
-					) ->
-						Type.map_expr run e
-				| TCall(
-						{ eexpr = TField( _, FStatic({ cl_path = ([], "Std") }, { cf_name = ("is" | "isOfType") }) ) },
-						[ obj; { eexpr = TTypeExpr(md) }]
-					) ->
-					let md = change_md md in
-					let mk_is obj md =
-						{ e with eexpr = TCall( { eexpr = TIdent "__is__"; etype = t_dynamic; epos = e.epos }, [
-							obj;
-							{ eexpr = TTypeExpr md; etype = t_dynamic (* this is after all a syntax filter *); epos = e.epos }
-						] ) }
-					in
-
-					let mk_or a b =
-						{
-							eexpr = TBinop(Ast.OpBoolOr, a, b);
-							etype = basic.tbool;
-							epos = e.epos
-						}
-					in
-
-					let wrap_if_needed obj f =
-						(* introduce temp variable for complex expressions *)
-						match obj.eexpr with
-							| TLocal(v) -> f obj
-							| _ ->
-								let var = mk_temp "isOfType" obj.etype in
-								let added = { obj with eexpr = TVar(var, Some(obj)); etype = basic.tvoid } in
-								let local = mk_local var obj.epos in
-								{
-									eexpr = TBlock([ added; f local ]);
-									etype = basic.tbool;
-									epos = e.epos
-								}
-					in
-
-					let obj = run obj in
-					(match follow_module follow md with
-						| TAbstractDecl{ a_path = ([], "Float") } when not (in_runtime_class gen) ->
-							(* on the special case of seeing if it is a Float, we need to test if both it is a float and if it is an Int *)
-							let mk_is local =
-								(* we check if it float or int or uint *)
-								let eisint = mk_is local (TAbstractDecl (get_ab_from_t basic.tint)) in
-								let eisuint = mk_is local (TAbstractDecl (get_ab_from_t uint)) in
-								let eisfloat = mk_is local md in
-								mk_paren (mk_or eisfloat (mk_or eisint eisuint))
-							in
-							wrap_if_needed obj mk_is
-
-						| TAbstractDecl{ a_path = ([], "Int") } when not (in_runtime_class gen) ->
-							(* int can be stored in double variable because of anonymous functions, check that case *)
-							let mk_isint_call local =
-								{
-									eexpr = TCall(
-										mk_static_field_access_infer runtime_cl "isInt" e.epos [],
-										[ local ]
-									);
-									etype = basic.tbool;
-									epos = e.epos
-								}
-							in
-							let mk_is local =
-								let eisint = mk_is local (TAbstractDecl (get_ab_from_t basic.tint)) in
-								let eisuint = mk_is local (TAbstractDecl (get_ab_from_t uint)) in
-								mk_paren (mk_or (mk_or eisint eisuint) (mk_isint_call local))
-							in
-							wrap_if_needed obj mk_is
-
-						| TAbstractDecl{ a_path = ([], "UInt") } when not (in_runtime_class gen) ->
-							(* uint can be stored in double variable because of anonymous functions, check that case *)
-							let mk_isuint_call local =
-								{
-									eexpr = TCall(
-										mk_static_field_access_infer runtime_cl "isUInt" e.epos [],
-										[ local ]
-									);
-									etype = basic.tbool;
-									epos = e.epos
-								}
-							in
-							let mk_is local =
-								let eisuint = mk_is local (TAbstractDecl (get_ab_from_t uint)) in
-								mk_paren (mk_or eisuint (mk_isuint_call local))
-							in
-							wrap_if_needed obj mk_is
-
-						| _ ->
-							mk_is obj md
-					)
-				(* end Std.is() *)
-
-				| TBinop( Ast.OpUShr, e1, e2 ) ->
-					mk_cast e.etype { e with eexpr = TBinop( Ast.OpShr, mk_cast uint (run e1), run e2 ) }
-
-				| TBinop( Ast.OpAssignOp Ast.OpUShr, e1, e2 ) ->
-					let mk_ushr local =
-						{ e with eexpr = TBinop(Ast.OpAssign, local, run { e with eexpr = TBinop(Ast.OpUShr, local, run e2) }) }
-					in
-
-					let mk_local obj =
-						let var = mk_temp "opUshr" obj.etype in
-						let added = { obj with eexpr = TVar(var, Some(obj)); etype = basic.tvoid } in
-						let local = mk_local var obj.epos in
-						local, added
-					in
-
-					let e1 = run e1 in
-
-					let ret = match e1.eexpr with
-						| TField({ eexpr = TLocal _ }, _)
-						| TField({ eexpr = TTypeExpr _ }, _)
-						| TArray({ eexpr = TLocal _ }, _)
-						| TLocal(_) ->
-							mk_ushr e1
-						| TField(fexpr, field) ->
-							let local, added = mk_local fexpr in
-							{ e with eexpr = TBlock([ added; mk_ushr { e1 with eexpr = TField(local, field) }  ]); }
-						| TArray(ea1, ea2) ->
-							let local, added = mk_local ea1 in
-							{ e with eexpr = TBlock([ added; mk_ushr { e1 with eexpr = TArray(local, ea2) }  ]); }
-						| _ -> (* invalid left-side expression *)
-							die "" __LOC__
-					in
-
-					ret
-
-				| _ -> Type.map_expr run e
-		in
-		gen.gsyntax_filters#add name (PCustom priority) run
-end;;
-
-(* ******************************************* *)
-(* CSharpSpecificSynf *)
-(* ******************************************* *)
-
-(*
-
-	Some CSharp-specific syntax filters  that can run after ExprUnwrap
-
-	dependencies:
-		Runs after ExprUnwrap
-
-*)
-
-module CSharpSpecificSynf =
-struct
-	let name = "csharp_specific"
-	let priority = solve_deps name [ DAfter ExpressionUnwrap.priority; DAfter ObjectDeclMap.priority; DAfter ArrayDeclSynf.priority;	DAfter HardNullableSynf.priority ]
-
-	let get_cl_from_t t =
-		match follow t with
-			| TInst(cl,_) -> cl
-			| _ -> die "" __LOC__
-
-	let is_tparam t =
-		match follow t with
-			| TInst( { cl_kind = KTypeParameter _ }, _ ) -> true
-			| _ -> false
-
-	let configure gen runtime_cl =
-		let basic = gen.gcon.basic in
-		(* let tchar = match ( get_type gen (["cs"], "Char16") ) with
-			| TTypeDecl t -> TType(t,[])
-			| TAbstractDecl a -> TAbstract(a,[])
-			| _ -> die "" __LOC__
-		in *)
-		let string_ext = get_cl ( get_type gen (["haxe";"lang"], "StringExt")) in
-		let ti64 = match ( get_type gen (["cs"], "Int64") ) with | TTypeDecl t -> TType(t,[]) | TAbstractDecl a -> TAbstract(a,[]) | _ -> die "" __LOC__ in
-		let boxed_ptr =
-			if Common.defined gen.gcon Define.Unsafe then
-				get_cl (get_type gen (["haxe";"lang"], "BoxedPointer"))
-				(* get_abstract (get_type gen (["cs"],"Pointer")) *)
-			else
-				null_class
-		in
-
-		let is_struct t = (* not basic type *)
-			match follow t with
-				| TInst(cl, _) when Meta.has Meta.Struct cl.cl_meta -> true
-				| _ -> false
-		in
-
-		let is_cl t = match gen.greal_type t with | TInst ( { cl_path = (["System"], "Type") }, [] ) -> true | _ -> false in
-
-		let fast_cast = Common.defined gen.gcon Define.FastCast in
-
-		let rec run e =
-			match e.eexpr with
-
-				(* Std.int() *)
-				| TCall(
-						{ eexpr = TField( _, FStatic({ cl_path = ([], "Std") }, { cf_name = "int" }) ) },
-						[obj]
-					) ->
-					run (mk_cast basic.tint obj)
-				(* end Std.int() *)
-
-				(* TODO: change cf_name *)
-				| TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = "length" })) ->
-					{ e with eexpr = TField(run ef, FDynamic "Length") }
-				| TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = "toLowerCase" })) ->
-					{ e with eexpr = TField(run ef, FDynamic "ToLowerInvariant") }
-				| TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = "toUpperCase" })) ->
-					{ e with eexpr = TField(run ef, FDynamic "ToUpperInvariant") }
-
-				| TCall( { eexpr = TField(_, FStatic({ cl_path = [], "String" }, { cf_name = "fromCharCode" })) }, [cc] ) ->
-					{ e with eexpr = TCall(mk_static_field_access_infer string_ext "fromCharCode" e.epos [], [run cc]) }
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charAt" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("charCodeAt" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("indexOf" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("lastIndexOf" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("split" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("substring" as field) })) }, args )
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("substr" as field) })) }, args ) ->
-					{ e with eexpr = TCall(mk_static_field_access_infer string_ext field e.epos [], [run ef] @ (List.map run args)) }
-				| TCall( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, { cf_name = ("toString") })) }, [] ) ->
-					run ef
-				| TNew( { cl_path = ([], "String") }, [], [p] ) -> run p (* new String(myString) -> myString *)
-
-				| TCast(expr, _) when like_float expr.etype && is_pointer gen e.etype ->
-					let expr = run expr in
-					mk_cast e.etype (mk_cast ti64 expr)
-				| TCast(expr, _) when is_dynamic gen expr.etype && is_pointer gen e.etype ->
-					(match get_ptr expr with
-						| None ->
-							(* unboxing *)
-							let expr = run expr in
-							mk_cast e.etype (mk_field_access gen (mk_cast (TInst(boxed_ptr,[])) expr) "value" e.epos)
-						| Some e ->
-							run e)
-				| TCast(expr, _) when is_pointer gen expr.etype && is_dynamic gen e.etype ->
-					(match get_ptr expr with
-						| None ->
-							(* boxing *)
-							let expr = run expr in
-							{ e with eexpr = TNew(boxed_ptr,[],[expr]) }
-						| Some e ->
-							run e)
-				| TCast(expr, _) when is_bool e.etype && is_dynamic gen expr.etype ->
-					{
-						eexpr = TCall(
-							mk_static_field_access_infer runtime_cl "toBool" expr.epos [],
-							[ run expr ]
-						);
-						etype = basic.tbool;
-						epos = e.epos
-					}
-				| TCast(expr, _) when is_int_float gen e.etype && is_dynamic gen expr.etype && ( Common.defined gen.gcon Define.EraseGenerics || not (is_null e.etype) ) && not (in_runtime_class gen) ->
-					let needs_cast = match gen.gfollow#run_f e.etype with
-						| TInst _ -> false
-						| _ -> true
-					in
-
-					let fun_name = if like_int e.etype then "toInt" else "toDouble" in
-
-					let ret = {
-						eexpr = TCall(
-							mk_static_field_access_infer runtime_cl fun_name expr.epos [],
-							[ run expr ]
-						);
-						etype = basic.tint;
-						epos = expr.epos
-					} in
-
-					if needs_cast then mk_cast e.etype ret else ret
-
-				| TCast(expr, _) when Common.defined gen.gcon Define.EraseGenerics && like_i64 e.etype && is_dynamic gen expr.etype && not (in_runtime_class gen) ->
-					{
-						eexpr = TCall(
-							mk_static_field_access_infer runtime_cl "toLong" expr.epos [],
-							[ run expr ]
-						);
-						etype = ti64;
-						epos = expr.epos
-					}
-
-				| TCast(expr, Some(TClassDecl cls)) when fast_cast && cls == null_class ->
-					if is_cs_basic_type (gen.greal_type e.etype) || is_tparam (gen.greal_type e.etype) then
-						{ e with eexpr = TCast(run expr, Some(TClassDecl null_class)) }
-					else
-						{ e with eexpr = TCall(mk (TIdent "__as__") t_dynamic e.epos, [run expr]) }
-
-				| TCast(expr, _) when (is_string e.etype) && (not (is_string expr.etype)) && not (in_runtime_class gen) ->
-					{ e with eexpr = TCall( mk_static_field_access_infer runtime_cl "toString" expr.epos [], [run expr] ) }
-
-				| TCast(expr, _) when is_tparam e.etype && not (in_runtime_class gen) && not (Common.defined gen.gcon Define.EraseGenerics) ->
-					let static = mk_static_field_access_infer (runtime_cl) "genericCast" e.epos [e.etype] in
-					{ e with eexpr = TCall(static, [mk (TIdent "$type_param") e.etype expr.epos; run expr]); }
-
-				| TBinop( (Ast.OpNotEq as op), e1, e2)
-				| TBinop( (Ast.OpEq as op), e1, e2) when is_struct e1.etype || is_struct e2.etype ->
-					let mk_ret e = match op with | Ast.OpNotEq -> { e with eexpr = TUnop(Ast.Not, Ast.Prefix, e) } | _ -> e in
-					mk_ret { e with
-						eexpr = TCall({
-							eexpr = TField(run e1, FDynamic "Equals");
-							etype = TFun(["obj1",false,t_dynamic;], basic.tbool);
-							epos = e1.epos
-						}, [ run e2 ])
-					}
-
-				| TBinop ( (Ast.OpEq as op), e1, e2 )
-				| TBinop ( (Ast.OpNotEq as op), e1, e2 ) when is_cl e1.etype && not (in_runtime_class gen) ->
-					let static = mk_static_field_access_infer (runtime_cl) "typeEq" e.epos [] in
-					let ret = { e with eexpr = TCall(static, [run e1; run e2]); } in
-					if op = Ast.OpNotEq then
-						{ ret with eexpr = TUnop(Ast.Not, Ast.Prefix, ret) }
-					else
-						ret
-
-				| _ -> Type.map_expr run e
-		in
-		gen.gsyntax_filters#add name (PCustom priority) run
-end;;
-
-let add_cast_handler gen =
-	let basic = gen.gcon.basic in
-	(*
-		starting to set gtparam_cast.
-	*)
-
-	(* NativeArray: the most important. *)
-
-	(*
-		var new_arr = new NativeArray<TO_T>(old_arr.Length);
-		var i = -1;
-		while( i < old_arr.Length )
-		{
-			new_arr[i] = (TO_T) old_arr[i];
-		}
-	*)
-
-	let native_arr_cl = get_cl ( get_type gen (["cs"], "NativeArray") ) in
-
-	let get_narr_param t = match follow t with
-		| TInst({ cl_path = (["cs"], "NativeArray") }, [param]) -> param
-		| _ -> die "" __LOC__
-	in
-
-	let gtparam_cast_native_array e to_t =
-		let old_param = get_narr_param e.etype in
-		let new_param = get_narr_param to_t in
-
-		let new_v = mk_temp "new_arr" to_t in
-		let i = mk_temp "i" basic.tint in
-		let old_len = mk_field_access gen e "Length" e.epos in
-		let obj_v = mk_temp "obj" t_dynamic in
-		let check_null = {eexpr = TBinop(Ast.OpNotEq, e, null e.etype e.epos); etype = basic.tbool; epos = e.epos} in
-		let block = [
-			{
-				eexpr = TVar(
-					new_v, Some( {
-						eexpr = TNew(native_arr_cl, [new_param], [old_len] );
-						etype = to_t;
-						epos = e.epos
-					} )
-				);
-				etype = basic.tvoid;
-				epos = e.epos
-			};
-			{
-				eexpr = TVar(i, Some( make_int gen.gcon.basic (-1) e.epos ));
-				etype = basic.tvoid;
-				epos = e.epos
-			};
-			{
-				eexpr = TWhile(
-					{
-						eexpr = TBinop(
-							Ast.OpLt,
-							{ eexpr = TUnop(Ast.Increment, Ast.Prefix, mk_local i e.epos); etype = basic.tint; epos = e.epos },
-							old_len
-						);
-						etype = basic.tbool;
-						epos = e.epos
-					},
-					{ eexpr = TBlock [
-						{
-							eexpr = TVar(obj_v, Some (mk_cast t_dynamic { eexpr = TArray(e, mk_local i e.epos); etype = old_param; epos = e.epos }));
-							etype = basic.tvoid;
-							epos = e.epos
-						};
-						{
-							eexpr = TIf({
-								eexpr = TBinop(Ast.OpNotEq, mk_local obj_v e.epos, null e.etype e.epos);
-								etype = basic.tbool;
-								epos = e.epos
-							},
-							{
-								eexpr = TBinop(
-									Ast.OpAssign,
-									{ eexpr = TArray(mk_local new_v e.epos, mk_local i e.epos); etype = new_param; epos = e.epos },
-									mk_cast new_param (mk_local obj_v e.epos)
-								);
-								etype = new_param;
-								epos = e.epos
-							},
-							None);
-							etype = basic.tvoid;
-							epos = e.epos
-						}
-					]; etype = basic.tvoid; epos = e.epos },
-					Ast.NormalWhile
-				);
-				etype = basic.tvoid;
-				epos = e.epos;
-			};
-			mk_local new_v e.epos
-		] in
-		{
-			eexpr = TIf(
-				check_null,
-				{
-					eexpr = TBlock(block);
-					etype = to_t;
-					epos = e.epos;
-				},
-				Some(null new_v.v_type e.epos)
-			);
-			etype = to_t;
-			epos = e.epos;
-		}
-	in
-
-	Hashtbl.add gen.gtparam_cast (["cs"], "NativeArray") gtparam_cast_native_array;
-	Hashtbl.add gen.gtparam_cast (["haxe";"lang"], "Null") (fun e to_t -> mk_cast to_t e)
-	(* end set gtparam_cast *)
-
-let connecting_string = "?" (* ? see list here http://www.fileformat.info/info/unicode/category/index.htm and here for C# http://msdn.microsoft.com/en-us/library/aa664670.aspx *)
-let default_package = "cs" (* I'm having this separated as I'm still not happy with having a cs package. Maybe dotnet would be better? *)
-let strict_mode = ref false (* strict mode is so we can check for unexpected information *)
-
-(* reserved c# words *)
-let reserved = let res = Hashtbl.create 120 in
-	List.iter (fun lst -> Hashtbl.add res lst ("@" ^ lst)) ["abstract"; "as"; "base"; "bool"; "break"; "byte"; "case"; "catch"; "char"; "checked"; "class";
-		"const"; "continue"; "decimal"; "default"; "delegate"; "do"; "double"; "else"; "enum"; "event"; "explicit";
-		"extern"; "false"; "finally"; "fixed"; "float"; "for"; "foreach"; "goto"; "if"; "implicit"; "in"; "int";
-		"interface"; "internal"; "is"; "lock"; "long"; "namespace"; "new"; "null"; "object"; "operator"; "out"; "override";
-		"params"; "private"; "protected"; "public"; "readonly"; "ref"; "return"; "sbyte"; "sealed"; "short"; "sizeof";
-		"stackalloc"; "static"; "string"; "struct"; "switch"; "this"; "throw"; "true"; "try"; "typeof"; "uint"; "ulong";
-		"unchecked"; "unsafe"; "ushort"; "using"; "virtual"; "volatile"; "void"; "while"; "add"; "ascending"; "by"; "descending";
-		"dynamic"; "equals"; "from"; "get"; "global"; "group"; "into"; "join"; "let"; "on"; "orderby"; "partial";
-		"remove"; "select"; "set"; "value"; "var"; "where"; "yield"; "await"];
-	res
-
-let dynamic_anon = mk_anon (ref Closed)
-
-let rec get_class_modifiers meta cl_type cl_access cl_modifiers =
-	match meta with
-		| [] -> cl_type,cl_access,cl_modifiers
-		| (Meta.Struct,[],_) :: meta -> get_class_modifiers meta "struct" cl_access cl_modifiers
-		| (Meta.Protected,[],_) :: meta -> get_class_modifiers meta cl_type "protected" cl_modifiers
-		| (Meta.Internal,[],_) :: meta -> get_class_modifiers meta cl_type "internal" cl_modifiers
-		(* no abstract for now | (":abstract",[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("abstract" :: cl_modifiers)
-		| (":static",[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("static" :: cl_modifiers) TODO: support those types *)
-		| (Meta.Unsafe,[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("unsafe" :: cl_modifiers)
-		| _ :: meta -> get_class_modifiers meta cl_type cl_access cl_modifiers
-
-let rec get_fun_modifiers meta access modifiers =
-	match meta with
-		| [] -> access,modifiers
-		| (Meta.Private,[],_) :: meta -> get_fun_modifiers meta "private" modifiers
-		| (Meta.Protected,[],_) :: meta -> get_fun_modifiers meta "protected" modifiers
-		| (Meta.Internal,[],_) :: meta -> get_fun_modifiers meta "internal" modifiers
-		| (Meta.ReadOnly,[],_) :: meta -> get_fun_modifiers meta access ("readonly" :: modifiers)
-		| (Meta.Unsafe,[],_) :: meta -> get_fun_modifiers meta access ("unsafe" :: modifiers)
-		| (Meta.Volatile,[],_) :: meta -> get_fun_modifiers meta access ("volatile" :: modifiers)
-		| (Meta.Custom ("?prop_impl" | ":cs_event_impl"),[],_) :: meta -> get_fun_modifiers meta "private" modifiers
-		| _ :: meta -> get_fun_modifiers meta access modifiers
-
-let generate con =
-	(try
-		let gen = new_ctx con in
-		let basic = con.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;
-
-		(* 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 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 | _ -> die "" __LOC__);
-		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
-			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
-			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_class_field cl name =
-			let change_ctor name = if name = "new" then snd cl.cl_path else name in
-			let rec gen name =
-				let name = name ^ "_" ^ name in
-				if PMap.mem name cl.cl_fields || PMap.mem name cl.cl_statics then gen name
-				else name
-			in
-			change_id (if name = snd cl.cl_path then gen name else (change_ctor name))
-		in
-		let change_enum_field enum name =
-			let rec gen name =
-				let name = name ^ "_" ^ name in
-				if PMap.mem name enum.e_constrs then gen name
-				else name
-			in
-			change_id (if name = snd enum.e_path then gen name else name)
-		in
-		let change_field = change_id in
-		let write_id w name = write w (change_id name) in
-		let write_class_field cl w name = write w (change_class_field cl name) in
-		let write_enum_field enum w name = write w (change_enum_field enum name) in
-		let write_field w name = write w (change_field name) in
-		let get_write_field field_access =
-			match field_access with
-			| FInstance (cl,_,f) | FStatic (cl,f) | FClosure (Some (cl,_),f) -> write_class_field cl
-			| FEnum (enum,f) -> write_enum_field enum
-			| _ -> write_field
-		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 =
-			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
-
-		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
-				| TAbstract (({ a_path = [],"Null" } as tab),[t2]) ->
-						Some (TAbstract(tab,[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 ifaces = Hashtbl.create 1 in
-
-		let ti64 = match ( get_type gen (["cs"], "Int64") ) with | TTypeDecl t -> TType(t,[]) | TAbstractDecl a -> TAbstract(a,[]) | _ -> die "" __LOC__ 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 rec real_type stack t =
-			let t = gen.gfollow#run_f t in
-			if List.exists (fast_eq t) stack then
-				t_dynamic
-			else begin
-				let stack = t :: stack in
-				let ret = match t with
-					| TAbstract({ a_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 stack t
-						else
-							(match real_type stack t with
-								| TInst( { cl_kind = KTypeParameter _ }, _ ) -> TInst(null_t, [t])
-								| t when is_cs_basic_type t -> TInst(null_t, [t])
-								| _ -> real_type stack t)
-					| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-						real_type stack (Abstract.get_underlying_type a pl)
-					| TAbstract ({ a_path = (["cs";"_Flags"], "EnumUnderlying") }, [t]) ->
-						real_type stack 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"]),"Rest" }, _ )
-					| TType( { t_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 stack (TClassDecl cl) params)
-					| 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
-			end
-		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 stack 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 (RealTypeParams.is_hxgeneric md) in
-			let ret t =
-				let t_changed = real_type stack t in
-				match is_hxgeneric, t_changed with
-				(*
-					Because Null<> types need a special compiler treatment for many operations (e.g. boxing/unboxing),
-					Null<> type parameters will be transformed into Dynamic.
-				*)
-				| _, TInst ( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> dynamic_anon
-				| false, _ -> t
-				| true, TInst ( { cl_path = ([], "String") }, _ ) -> t
-				| 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
-
-		let real_type = real_type []
-		and change_param_type = change_param_type [] 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.tm_type 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) ^ " ]"); die "" __LOC__ 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 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 (UCharExt.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 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_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 = StringHelper.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 = TIdent "$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, _), FNotFound when (has_class_flag cl CExtern) && (has_class_flag cl CInterface) ->
-				not (is_hxgen (TClassDecl cl))
-			| _, FClassField(_,_,decl,v,_,t,_) ->
-				not (Type.is_physical_field v) && (Meta.has Meta.Property v.cf_meta || ((has_class_flag decl CExtern) && 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, _), FNotFound when (has_class_flag cl CExtern) && (has_class_flag cl CInterface) ->
-				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 = TIdent ("__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 _, _, _)
-				| TIdent "__fallback__"
-				| TIdent "__sbreak__" ->
-					ret := expr :: !ret
-				| TConst _
-				| TLocal _
-				| TArray _
-				| TBinop _
-				| TField _
-				| TEnumParameter _
-				| TTypeExpr _
-				| TObjectDecl _
-				| TArrayDecl _
-				| TCast _
-				| 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
-
-		let expr_s is_in_value w e =
-			last_line := -1;
-			in_value := is_in_value;
-			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
-							| _ -> die "" __LOC__
-						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 ".";
-							(get_write_field f) 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 ".";
-							(get_write_field f) 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
-							if not was_in_value then
-								write w "{}"
-							else begin
-								expr_s w ef;
-								write w ".";
-								(get_write_field f) 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 ".";
-							(get_write_field f) w propname;
-							write w " = ";
-							expr_s w v
-						end else
-							do_call w e [v]
-					| TField (e, ((FStatic(_, cf) | FInstance(_, _, cf)) as f)) 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 "."; (get_write_field f) w s
-							| _ :: tl -> loop tl
-							| [] -> expr_s w e; write w "."; (get_write_field f) 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 ->
-								let s = Texpr.replace_separators s "" in
-								let len = String.length s in
-								let rec loop i prev_c =
-									if i >= len then begin
-										write w s;
-										if prev_c = '.' then write w "0"
-									end else begin
-										let c = String.unsafe_get s i in
-										if (c = 'e' || c = 'E') && prev_c = '.' then
-											let first = String.sub s 0 i in
-											let second = String.sub s i (len - i) in
-											write w first;
-											write w "0";
-											write w second
-										else
-											loop (i + 1) c
-									end
-								in
-								loop 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 ")"
-					| TIdent "__sbreak__" -> write w "break"
-					| TIdent "__undefined__" ->
-						write w (t_s (TInst(runtime_cl, List.map (fun _ -> t_dynamic) runtime_cl.cl_params)));
-						write w ".undefined";
-					| TIdent "__typeof__" -> write w "typeof"
-					| TIdent "__sizeof__" -> write w "sizeof"
-					| TLocal var ->
-						write_id w var.v_name
-					| TField (_, (FEnum(e, ef) as f)) ->
-						let s = ef.ef_name in
-						print w "%s." ("global::" ^ module_s (TEnumDecl e)); (get_write_field f) 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
-					(* hack to dodge #7034 *)
-					| TBinop (OpMod,_,e2) when (match (Texpr.skip e2).eexpr with TConst (TInt i32) -> i32 = Int32.zero | _ -> false) ->
-						write w ("System.Double.NaN")
-					| 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 c when (has_class_flag c CInterface) ->
-									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 ".";
-						(get_write_field s) 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 "->"; (get_write_field s) w (field_name s)
-					| TField (e, s) ->
-						expr_s w e; write w "."; (get_write_field s) 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 ((Meta.LoopLabel,[(EConst(Int (n, _)),_)],_), e) ->
-						(match e.eexpr with
-						| TFor _ | TWhile _ ->
-							expr_s w e;
-							print w "label%s: {}" n
-						| TBreak -> print w "goto label%s" n
-						| _ -> die "" __LOC__)
-					| TMeta (_,e) ->
-								expr_s w e
-					| TArrayDecl el
-					| TCall ({ eexpr = TIdent "__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 = TIdent "__delegate__" }, [del]) ->
-						expr_s w del
-					| TCall ({ eexpr = TIdent "__is__" }, [ expr; { eexpr = TTypeExpr(md) } ] ) ->
-						write w "( ";
-						expr_s w expr;
-						write w " is ";
-						write w (md_s md);
-						write w " )"
-					| TCall ({ eexpr = TIdent "__as__" }, [ expr; { eexpr = TTypeExpr(md) } ] ) ->
-						write w "( ";
-						expr_s w expr;
-						write w " as ";
-						write w (md_s md);
-						write w " )"
-					| TCall ({ eexpr = TIdent "__as__" }, expr :: _ ) ->
-						write w "( ";
-						expr_s w expr;
-						write w " as ";
-						write w (t_s e.etype);
-						write w " )";
-					| TCall({ eexpr = TField (_, FStatic ({ cl_path = ["cs"],"Syntax" }, { cf_name = meth })) }, args) ->
-						gen_syntax meth args e.epos
-					| TCall ({ eexpr = TIdent "__cs__" }, [ { eexpr = TConst(TString(s)) } ] ) ->
-						write w s
-					| TCall ({ eexpr = TIdent "__cs__" }, { eexpr = TConst(TString(s)) } :: tl ) ->
-						Codegen.interpolate_code gen.gcon s tl (write w) (expr_s w) e.epos
-					| TCall ({ eexpr = TIdent "__stackalloc__" }, [ e ] ) ->
-						write w "stackalloc byte[";
-						expr_s w e;
-						write w "]"
-					| TCall ({ eexpr = TIdent "__unsafe__" }, [ e ] ) ->
-						write w "unsafe ";
-						begin_block w;
-						expr_s w (mk_block e);
-						write w ";";
-						end_block w
-					| TCall ({ eexpr = TIdent "__checked__" }, [ e ] ) ->
-						write w "checked";
-						expr_s w (mk_block e)
-					| TCall ({ eexpr = TIdent "__lock__" }, [ eobj; eblock ] ) ->
-						write w "lock(";
-						expr_s w eobj;
-						write w ")";
-						expr_s w (mk_block eblock)
-					| TCall ({ eexpr = TIdent "__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 = TIdent "__addressOf__" }, [ e ] ) ->
-						let e = ensure_local e "for addressOf" in
-						write w "&";
-						expr_s w e
-					| TCall ({ eexpr = TIdent "__valueOf__" }, [ e ] ) ->
-						write w "*(";
-						expr_s w e;
-						write w ")"
-					(* 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 (Spread, Prefix, e) ->
-						expr_s w e
-					| 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 ->
-							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 (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);
-							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 { eexpr = TIdent "__rethrow__" } ->
-						write w "throw"
-					| TThrow { eexpr = TLocal(v) } when (has_var_flag v VCaught) ->
-						write w "throw";
-					| 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 die "" __LOC__
-					| TObjectDecl _ -> write w "[ obj decl not supported ]"; if !strict_mode then die "" __LOC__
-					| TFunction _ -> write w "[ func decl not supported ]"; if !strict_mode then die "" __LOC__
-					| TEnumParameter _ -> write w "[ enum parameter not supported ]"; if !strict_mode then die "" __LOC__
-					| TEnumIndex _ -> write w "[ enum index not supported ]"; if !strict_mode then die "" __LOC__
-					| TIdent s -> write w "[ ident not supported ]"; if !strict_mode then die "" __LOC__
-				)
-			and gen_syntax meth args pos =
-				match meth, args with
-				| "code", code :: args ->
-					let code, code_pos =
-						match code.eexpr with
-						| TConst (TString s) -> s, code.epos
-						| _ -> abort "The `code` argument for cs.Syntax.code must be a string constant" code.epos
-					in
-					begin
-						let rec reveal_expr expr =
-							match expr.eexpr with
-								| TCast (e, _) | TMeta (_, e) -> reveal_expr e
-								| _ -> expr
-						in
-						let args = List.map
-							(fun arg ->
-								match (reveal_expr arg).eexpr with
-									| TIf _ | TBinop _ | TUnop _ -> { arg with eexpr = TParenthesis arg }
-									| _ -> arg
-							)
-							args
-						in
-						Codegen.interpolate_code gen.gcon code args (write w) (expr_s w) code_pos
-					end
-				| "plainCode", [code] ->
-					let code =
-						match code.eexpr with
-						| TConst (TString s) -> s
-						| _ -> abort "The `code` argument for cs.Syntax.plainCode must be a string constant" code.epos
-					in
-					write w (String.concat "\n" (ExtString.String.nsplit code "\r\n"))
-				| _ ->
-					abort (Printf.sprintf "Unknown cs.Syntax method `%s` with %d arguments" meth (List.length args)) pos
-			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)
-							| _ -> die "" __LOC__
-						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 []
-						| _ -> ()
-				in
-				write w "(";
-				let ft = match follow e.etype with
-					| TFun(args,_) -> args
-					| _ -> []
-				in
-
-				loop 0 el ft;
-
-				write w ")"
-			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 gen_assembly_attributes w metadata =
-			List.iter (function
-				| Meta.AssemblyMeta, [EConst(String(s,_)), _], _ ->
-					write w "[assembly:";
-					write w s;
-					write w "]";
-					newline w
-				| Meta.AssemblyMeta, [meta], _ ->
-					write w "[assembly:";
-					gen_spart w meta;
-					write w "]";
-					newline w
-				| _ -> ()
-			) metadata
-		in
-
-		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
-
-		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 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.tm_type with
-						| Some t -> run t
-						| _ -> () (* avoid infinite loop / should be the same in this context *))
-					| TLazy f ->
-						run (lazy_type 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
-				| _ when ExtType.is_rest (Type.follow t) -> "params " ^ (t_s (Abstract.follow_with_abstracts 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 | _ -> die "" __LOC__ in
-					let combination_error c1 c2 =
-						gen.gcon.error ("The " ^ (get_constraint c1) ^ " constraint cannot be combined with the " ^ (get_constraint c2) ^ " constraint.") cl.cl_pos in
-
-					let params = sprintf "<%s>" (String.concat ", " (List.map (fun tp -> get_param_name tp.ttp_type) cl_params)) in
-					let params_extends =
-						if hxgen || not (Meta.has (Meta.NativeGen) cl.cl_meta) then
-							[""]
-						else
-							List.fold_left (fun acc {ttp_name=name;ttp_type=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 (c,_) when not (has_class_flag c CFinal) && not (has_class_flag c CInterface) ->
-													base_class_constraints := (CsConstraint (t_s t)) :: !base_class_constraints;
-													acc;
-
-												(* interface *)
-												| TInst (c, _) when (has_class_flag c CInterface) ->
-													(CsConstraint (t_s t)) :: acc
-
-												(* cs constraints *)
-												(* See https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters *)
-												| TAbstract({ a_path = (_, c); a_module = { m_path = ([pack],"Constraints") } }, params) ->
-													(match pack, c with
-														| "haxe", "Constructible" ->
-															(match params with
-																(* Only for parameterless constructors *)
-																| [TFun ([],TAbstract({a_path=[],"Void"},_))] ->
-																	if (List.memq CsStruct acc) then combination_error CsConstructible CsStruct;
-																	if (List.memq CsUnmanaged acc) then combination_error CsUnmanaged CsConstructible;
-																	CsConstructible :: acc;
-																| _ -> acc;
-															)
-														| "cs", "CsStruct" ->
-															if (List.memq CsClass acc) then combination_error CsClass CsStruct;
-															if (List.memq CsConstructible acc) then combination_error CsConstructible CsStruct;
-															if (List.memq CsUnmanaged acc) then combination_error CsUnmanaged CsStruct;
-															CsStruct :: acc;
-														| "cs", "CsUnmanaged" ->
-															if (List.memq CsStruct acc) then combination_error CsUnmanaged CsStruct;
-															if (List.memq CsConstructible acc) then combination_error CsUnmanaged CsConstructible;
-															CsUnmanaged :: acc;
-														| "cs", "CsClass" ->
-															if (List.memq CsStruct acc) then combination_error CsClass CsStruct;
-															CsClass :: acc;
-														| _, _ -> acc;
-													)
-
-												(* skip anything other *)
-												| _ ->
-													acc
-										) [] constraints in
-
-										let s_constraints = (List.sort
-											(* C# expects some ordering for built-in constraints: *)
-											(fun c1 c2 -> match c1, c2 with
-												| a, b when a == b -> 0
-												(* - "new()" type constraint should be last *)
-												| CsConstructible, _ -> 1
-												| _, CsConstructible -> -1
-												(* - "class", "struct" and "unmanaged" should be first *)
-												| CsClass, _ | CsStruct, _ | CsUnmanaged, _ -> -1
-												| _, CsClass | _, CsStruct | _, CsUnmanaged -> 1
-												| _, _ -> 0
-										) (!base_class_constraints @ other_constraints)) in
-
-										if s_constraints <> [] then
-											(sprintf " where %s : %s" (get_param_name t) (String.concat ", " (List.map get_constraint 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 = (has_class_flag cl CInterface) 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_class_field cl 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 rec gen_prop w is_static cl is_final (prop,t,get,set) =
-			gen_attributes w prop.cf_meta;
-			let is_interface = (has_class_flag cl CInterface) in
-			let fn_is_final = function
-				| None -> true
-				| Some ({ cf_kind = Method mkind } as m) ->
-					(match mkind with | MethInline -> true | _ -> false) || (has_class_field_flag m CfFinal)
-				| _ -> die "" __LOC__
-			in
-			let is_virtual = not (is_interface || is_final || (has_class_field_flag prop CfFinal) || fn_is_final get || fn_is_final set) in
-
-			let fn_is_override = function
-				| Some cf -> has_class_field_flag cf CfOverride
-				| 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_class_field cl 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;
-
-			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 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 = TIdent "__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 rec gen_class_field w ?(is_overload=false) is_static cl is_final cf =
-			gen_attributes w cf.cf_meta;
-			let is_interface = (has_class_flag cl CInterface) in
-			let name, is_new, is_explicit_iface = match cf.cf_name with
-				| "new" -> cf.cf_name, 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 Type.is_physical_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_class_field cl name);
-						(match cf.cf_expr with
-							| Some e ->
-								write w " = ";
-								expr_s true w e;
-								write w ";"
-							| None when (Meta.has Meta.Property cf.cf_meta) ->
-								write w " { get; set; }";
-							| None ->
-								write w ";"
-						);
-					end (* TODO see how (get,set) variable handle when they are interfaces *)
-				| Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
-					List.iter (fun cf -> if (has_class_flag cl CInterface) || cf.cf_expr <> None then
-						gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
-					) cf.cf_overloads
-				| Var _ | Method MethDynamic -> ()
-				| Method _ when is_new && Meta.has Meta.Struct cl.cl_meta && fst (get_fun cf.cf_type) = [] ->
-						(* make sure that the method is empty *)
-						let rec check_empty expr = match expr.eexpr with
-							| TBlock(bl) -> bl = [] || List.for_all check_empty bl
-							| TMeta(_,e) -> check_empty e
-							| TParenthesis(e) -> check_empty e
-							| TConst(TNull) -> true
-							| TFunction(tf) -> check_empty tf.tf_expr
-							| _ -> false
-						in
-						(match cf.cf_expr with
-							| Some e ->
-								if not (check_empty e) then
-									gen.gcon.error "The body of a zero argument constructor of a struct should be empty" e.epos
-							| _ -> ());
-						List.iter (fun cf ->
-							if (has_class_flag cl CInterface) || cf.cf_expr <> None then
-								gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
-						) cf.cf_overloads;
-				| Method mkind ->
-					let overloads =
-						match cf.cf_overloads with
-						| [] when is_overload -> []
-						| [] when has_meta Meta.NativeGen cl.cl_meta ->
-							get_overloads_for_optional_args gen cl cf is_static
-						| overloads -> overloads
-					in
-					List.iter (fun cf ->
-						if (has_class_flag cl CInterface) || (has_class_flag cl CAbstract) || cf.cf_expr <> None then
-							gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) 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 || (has_class_field_flag cf CfFinal) then false else is_virtual in
-					let is_override = has_class_field_flag cf CfOverride 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_abstract = has_class_field_flag cf CfAbstract in
-					let is_virtual = is_virtual && not (has_class_flag cl CFinal) && not (is_interface) && not is_abstract 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 modifiers = if is_abstract then "abstract" :: modifiers else modifiers 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 (has_class_field_flag cf CfOverload) then match field_access gen (TInst(cl, extract_param_types cl.cl_params)) cf.cf_name with | FClassField(_,_,_,_,_,actual_t,_) -> actual_t | _ -> die "" __LOC__ else cf.cf_type in
-					let ret_type, args = match follow cf_type with | TFun (strbtl, t) -> (t, strbtl) | _ -> die "" __LOC__ 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_class_field cl 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 || is_abstract 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)
-												| _ -> die "" __LOC__ (* 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 = Timer.timer ["expression to string"] in
-											expr_s false w e;
-											t();
-											line_reset_directive w;
-											if unchecked then end_block w
-										| _ ->
-											die "" __LOC__
-									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
-											(* auto-generated ctor overloading for optional args (see get_overloads_for_optional_args) *)
-											| TBlock([{ eexpr = TCall ({ eexpr = TConst TThis }, args) } as this_call]) ->
-												write w ": ";
-												let t = Timer.timer ["expression to string"] in
-												expr_s false w this_call;
-												write w " ";
-												t();
-												write w "{}"
-											| TBlock(bl) ->
-												let super_call, rest = get_super_call bl in
-												(match super_call with
-													| None -> ()
-													| Some sc ->
-														write w ": ";
-														let t = Timer.timer ["expression to string"] in
-														expr_s false w sc;
-														write w " ";
-														t()
-												);
-												write_method_expr { expr with eexpr = TBlock(rest) }
-											| _ -> die "" __LOC__
-									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
-
-		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.gwarning WGenerator "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.gwarning WGenerator "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.gwarning WGenerator "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";
-						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; die "" __LOC__
-				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 (has_class_flag cl CInterface) && 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 (has_class_flag cl CInterface) then raise Not_found;
-				let cf = PMap.find "toString" cl.cl_fields in
-				(if has_class_field_flag cf CfOverride 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 (has_class_flag cl CInterface) then raise Not_found;
-				let cf = PMap.find "finalize" cl.cl_fields in
-				(if has_class_field_flag cf CfOverride 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 Type.is_physical_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
-							make_static_this cl f.cf_pos
-						else
-							{ eexpr = TConst TThis; etype = TInst(cl,extract_param_types 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;
-							write w "return ";
-							expr_s true w this;
-							print w ".get_%s();" f.cf_name;
-							end_block w
-						| _ -> ());
-						(match v.v_write with
-						| AccCall ->
-							write w "set";
-							begin_block w;
-							expr_s false 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 is_first_type =
-			if (is_first_type == false) then begin
-				if Meta.has Meta.AssemblyStrict cl.cl_meta then
-					gen.gcon.error "@:cs.assemblyStrict can only be used on the first class of a module" cl.cl_pos
-				else if Meta.has Meta.AssemblyMeta cl.cl_meta then
-					gen.gcon.error "@:cs.assemblyMeta can only be used on the first class of a module" cl.cl_pos;
-			end;
-
-			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
-				| [] ->
-					(* Should the assembly annotations be added to the class in this case? *)
-
-					if Meta.has Meta.AssemblyStrict cl.cl_meta then
-						gen.gcon.error "@:cs.assemblyStrict cannot be used on top level modules" cl.cl_pos
-					else if Meta.has Meta.AssemblyMeta cl.cl_meta then
-						gen.gcon.error "@:cs.assemblyMeta cannot be used on top level modules" cl.cl_pos;
-
-					false
-				| ns ->
-					gen_assembly_attributes w cl.cl_meta;
-					print w "namespace %s " (String.concat "." ns);
-					begin_block w;
-					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 | _ -> die "" __LOC__) [] in
-				cl.cl_meta <- (Meta.Meta, [
-					EConst(String("global::haxe.lang.GenericInterface(typeof(global::" ^ module_s (TClassDecl cl) ^ "<" ^ String.concat ", " tparams ^ ">))",SDoubleQuotes) ), cl.cl_pos
-				], cl.cl_pos) :: cl.cl_meta
-			with Not_found ->
-				());
-
-			gen_attributes w cl.cl_meta;
-
-			let main_expr =
-				match gen.gentry_point with
-				| Some (_,({ cl_path = (_,"Main") } as cl_main),expr) when cl == cl_main && not (has_class_flag cl CInterface) ->
-					(*
-						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);
-					expr_s false w expr;
-					write w ";";
-					end_block w;
-					end_block w;
-					newline w;
-					None
-				| Some (_, cl_main,expr) when cl == cl_main && not (has_class_flag cl CInterface) -> Some expr
-				| _ -> None
-			in
-
-			let clt, access, modifiers = get_class_modifiers cl.cl_meta (if (has_class_flag cl CInterface) then "interface" else "class") "public" [] in
-			let modifiers = if is_module_fields_class cl then "static" :: modifiers else if (has_class_flag cl CFinal) then "sealed" :: modifiers else modifiers in
-			let is_final = clt = "struct" || (has_class_flag cl CFinal) in
-
-			let modifiers = [access] @ modifiers in
-			let is_abstract = has_class_flag cl CAbstract in
-			let modifiers = if is_abstract then "abstract" :: modifiers else 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 die "" __LOC__;*)
-
-			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;
-
-			Option.may (fun expr ->
-				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);
-				expr_s false w expr;
-				write w ";";
-				end_block w
-			) main_expr;
-
-			(match cl.cl_init with
-				| None -> ()
-				| Some init ->
-					let needs_block,write_expr =
-						let unchecked = needs_unchecked init in
-						if cl.cl_params = [] then
-							unchecked, (fun() ->
-								if unchecked then write w "unchecked";
-								expr_s false w (mk_block init)
-							)
-						else begin
-							write w "static bool __hx_init_called = false;";
-							newline w;
-							true, (fun() ->
-								let flag = (t_s (TInst(cl, List.map (fun _ -> t_empty) cl.cl_params))) ^ ".__hx_init_called" in
-								write w ("if(" ^ flag ^ ") return;");
-								newline w;
-								write w (flag ^ " = true;");
-								newline w;
-								if unchecked then write w "unchecked";
-								expr_s false w (mk_block init);
-								newline w
-							)
-						end
-					in
-					print w "static %s() " (snd cl.cl_path);
-					if needs_block then begin
-						begin_block w;
-						write_expr();
-						end_block w;
-					end else
-						write_expr();
-					line_reset_directive w;
-					newline w;
-					newline w
-			);
-
-			(* collect properties and events *)
-			let partition cf cflist =
-				let events, props, nonprops = ref [], ref [], ref [] in
-
-				List.iter (fun v -> match v.cf_kind with
-					| Var { v_read = AccCall } | Var { v_write = AccCall } when not (Type.is_physical_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, extract_param_types 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,extract_param_types cl.cl_params)) name ->
-							let ret = ref (v,t,None,None) in
-							props := (name, ret) :: !props;
-							ret
-						| _ -> raise Not_found
-				in
-
-				let find_event name = List.assoc name events in
-
-				let is_empty_function cf = match cf.cf_expr with
-					| Some {eexpr = TFunction { tf_expr = {eexpr = TBlock []}}} -> true
-					| _ -> false
-				in
-
-				let interf = (has_class_flag cl CInterface) 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 (has_class_flag cl CInterface) then
-							nonprops := add :: remove :: !nonprops
-					| _ -> die "" __LOC__ (* 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 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 (has_class_flag cl CInterface) 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 (has_class_flag cl CInterface) && cl.cl_ordered_statics <> [] then begin
-				print w "public class %s__Statics_" (snd cl.cl_path);
-				begin_block w;
-				remove_class_flag cl CInterface;
-				List.iter (gen_class_field w true cl is_final) cl.cl_ordered_statics;
-				add_class_flag cl CInterface;
-				end_block w
-			end;
-			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
-			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;
-
-			if should_close then end_block w
-		in
-
-		let module_type_gen w md_tp is_first_type =
-			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 (has_class_flag cl CExtern) then begin
-						(if requires_root then write w "using haxe.root;\n"; newline w;);
-
-						(if (Meta.has Meta.CsUsing cl.cl_meta) then
-							match (Meta.get Meta.CsUsing cl.cl_meta) with
-								| _,_,p when not !is_first_type ->
-									gen.gcon.error "@:cs.using can only be used on the first type of a module" p
-								| _,[],p ->
-									gen.gcon.error "One or several string constants expected" p
-								| _,e,_ ->
-									(List.iter (fun e ->
-										match e with
-										| (EConst(String(s,_))),_ -> write w (Printf.sprintf "using %s;\n" s)
-										| _,p -> gen.gcon.error "One or several string constants expected" p
-									) e);
-									newline w
-						);
-
-						gen_class w cl !is_first_type;
-						is_first_type := false;
-						newline w;
-						newline w
-					end;
-					(not (has_class_flag cl CExtern))
-				| 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;
-						is_first_type := false;
-						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 "__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;
-
-		(* 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 mk_tp t pos = { eexpr = TIdent "$type_param"; 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
-					| TConst (TInt _ | TFloat _ | TBool _), _ ->
-						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; die "" __LOC__
-			)
-			(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 explicit_fn_name c tl fname =
-			path_param_s (TClassDecl c) c.cl_path tl ^ "." ^ fname
-		in
-
-		FixOverrides.configure ~explicit_fn_name:explicit_fn_name ~get_vmtype:real_type gen;
-
-		let allowed_meta = Hashtbl.create 1 in
-		Hashtbl.add allowed_meta Meta.LoopLabel true;
-		Normalize.configure gen ~allowed_metas:allowed_meta;
-
-		AbstractImplementationFix.configure gen;
-
-		let cl_arg_exc = get_cl (get_type gen (["System"],"ArgumentException")) in
-		let cl_arg_exc_t = TInst (cl_arg_exc, []) in
-		let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [make_string gen.gcon.basic msg pos])) cl_arg_exc_t pos in
-		let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in
-		ClosuresToClass.configure gen closure_t;
-
-		let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in
-		let type_enumindex = mk_static_field_access_infer gen.gclasses.cl_type "enumIndex" null_pos [] in
-		let mk_enum_index_call e p =
-			mk (TCall (type_enumindex, [e])) gen.gcon.basic.tint p
-		in
-		EnumToClass2.configure gen enum_base mk_enum_index_call;
-
-		InterfaceVarsDeleteModf.configure gen;
-
-		let dynamic_object = (get_cl (get_type gen (["haxe";"lang"],"DynamicObject")) ) in
-
-		let object_iface = get_cl (get_type gen (["haxe";"lang"],"IHxObject")) in
-
-		let empty_en = match get_type gen (["haxe";"lang"], "EmptyObject") with TEnumDecl e -> e | _ -> die "" __LOC__ in
-		let empty_ctor_type = TEnum(empty_en, []) in
-		let empty_en_expr = mk (TTypeExpr (TEnumDecl empty_en)) (mk_anon (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_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 rcf_static_insert, rcf_static_remove =
-			let get_specialized_postfix t = match t with
-				| TAbstract({a_path = [],("Float" | "Int" as name)}, _) -> name
-				| TAnon _ | TDynamic _ -> "Dynamic"
-				| _ -> print_endline (debug_type t); die "" __LOC__
-			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 [])
-		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 is_unsafe = { eexpr = TConst(TBool is_unsafe); etype = basic.tbool; epos = pos } 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 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 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 hash_arg = match may_hash with
-				| None -> []
-				| Some h -> [ { eexpr = TConst(TInt h); etype = basic.tint; epos = field_expr.epos } ]
-			in
-
-			let arr_call = if args <> [] then
-				mk_nativearray_decl gen t_dynamic args ecall.epos
-			else
-				null (gen.gclasses.nativearray t_dynamic) ecall.epos
-			in
-
-			let call_args =
-				[field_expr; { field_expr with eexpr = TConst(TString field); etype = basic.tstring } ]
-					@ hash_arg
-					@ [ arr_call ]
-			in
-
-			mk_cast ecall.etype { ecall with eexpr = TCall(infer, call_args) }
-		in
-
-		add_cast_handler gen;
-		if not erase_generics then
-			RealTypeParams.configure gen (fun e t -> gen.gwarning WGenerator ("Cannot cast to " ^ (debug_type t)) e.epos; mk_cast t e) ifaces (get_cl (get_type gen (["haxe";"lang"], "IGenericObject")))
-		else
-			RealTypeParams.RealTypeParamsModf.configure gen (RealTypeParams.RealTypeParamsModf.set_only_hxgeneric gen);
-
-		let flookup_cl = get_cl (get_type gen (["haxe";"lang"], "FieldLookup")) in
-
-		let cl_field_exc = get_cl (get_type gen (["System"],"MemberAccessException")) in
-		let cl_field_exc_t = TInst (cl_field_exc, []) in
-		let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [make_string gen.gcon.basic msg pos])) cl_field_exc_t pos 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);
-					}
-				)
-				mk_field_exception
-		in
-
-		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 add_class_field_flag cf CfOverride
-			) 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_field = mk_static_field_access_infer runtime_cl "slowCallField" null_pos [] in
-		let slow_invoke ethis efield eargs =
-			mk (TCall (slow_invoke_field, [ethis; efield; eargs])) t_dynamic ethis.epos
-		in
-		ReflectionCFs.configure rcf_ctx object_iface ~slow_invoke:slow_invoke;
-
-		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)
-				| _ -> die "" __LOC__
-		) "__get" "__set";
-
-		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_dynamic_expr e = is_dynamic e.etype || match e.eexpr with
-			| TField(tf, f) -> field_is_dynamic tf.etype (f)
-			| _ -> false
-		in
-
-		let may_nullable t = match gen.gfollow#run_f t with
-			| TAbstract({ a_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 is_null t = match real_type t with
-			| TInst( { cl_path = (["haxe";"lang"], "Null") }, _ ) -> true
-			| _ -> 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 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
-
-		let string_cl = match gen.gcon.basic.tstring with
-			| TInst(c,[]) -> c
-			| _ -> die "" __LOC__
-		in
-
-		let is_undefined e = match e.eexpr with
-			| TIdent "__undefined__" | TField(_,FStatic({cl_path=["haxe";"lang"],"Runtime"},{cf_name="undefined"})) -> true
-			| _ -> false
-		in
-
-		let nullable_basic t = match gen.gfollow#run_f t with
-			| TType({ t_path = ([],"Null") }, [t])
-			| TAbstract({ a_path = ([],"Null") }, [t]) when is_cs_basic_type t ->
-				Some(t)
-			| _ ->
-				None
-		in
-
-		DynamicOperators.configure gen
-			~handle_strings:false
-			(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 e1.etype || is_dynamic e2.etype || 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 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 op e e1 e2 ->
-				match nullable_basic e1.etype, nullable_basic e2.etype with
-					| Some(t1), None when is_cs_basic_type e2.etype ->
-						{ e with eexpr = TBinop(op, mk_cast t1 e1, e2) }
-					| None, Some(t2) when is_cs_basic_type e1.etype ->
-						{ e with eexpr = TBinop(op, e1, mk_cast t2 e2) }
-					| _ ->
-							let handler = if is_string e1.etype then begin
-									{ e1 with eexpr = TCall(mk_static_field_access_infer string_cl "CompareOrdinal" 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
-							in
-							let zero = make_int gen.gcon.basic 0 e.epos in
-							{ e with eexpr = TBinop(op, handler, zero) }
-		);
-
-		FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);
-
-		ClassInstance.configure gen;
-
-		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
-					)
-				| _ -> die "" __LOC__
-		);
-
-		ExpressionUnwrap.configure gen;
-
-		(* UnnecessaryCastsRemoval.configure gen; *)
-
-		IntDivisionSynf.configure gen;
-
-		UnreachableCodeEliminationSynf.configure gen false;
-
-		ArraySpliceOptimization.configure gen;
-
-		ArrayDeclSynf.configure gen native_arr_cl change_param_type;
-
-		CSharpSpecificSynf.configure gen runtime_cl;
-		CSharpSpecificESynf.configure gen runtime_cl;
-
-		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
-				Path.mkdir_from_path full_path;
-
-				let f = open_out_bin full_path in
-				output_string f v;
-				close_out f;
-
-				out_files := (gen.gcon.file_keys#get 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
-
-		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 haxe_libs = List.filter (function net_lib -> is_some (net_lib#lookup (["haxe";"lang"], "DceNo"))) gen.gcon.native_libs.net_libs in
-		(try
-			(* first let's see if we're adding a -net-lib that has already a haxe.lang.FieldLookup *)
-			let net_lib = List.find (function net_lib -> is_some (net_lib#lookup (["haxe";"lang"], "FieldLookup"))) gen.gcon.native_libs.net_libs in
-			let name = net_lib#get_name in
-			if not (Common.defined gen.gcon Define.DllImport) then begin
-				gen.gwarning WGenerator ("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 net_lib -> net_lib#get_name = name) haxe_libs) then
-				gen.gwarning WGenerator ("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__ *)
-			add_class_flag flookup_cl CExtern;
-			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 c when not (has_class_flag c CExtern) && not (has_class_flag c CInterface) -> (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 c when not (has_class_flag c CExtern) -> (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 net_lib ->
-						is_some (net_lib#lookup path)) haxe_libs);
-					add_class_flag c CExtern;
-				with | Not_found -> ())
-				| _ -> ()) gen.gtypes
-		end;
-
-		RenameTypeParameters.run gen.gtypes_list;
-
-		Path.mkdir_from_path gen.gcon.file;
-
-		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 is_first_type = ref true in
-			let should_write = List.fold_left (fun should md -> module_type_gen w md is_first_type || 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 (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" in
-			let args = ["run"; "hxcs"; "hxcs_build.txt"; "--haxe-version"; (string_of_int gen.gcon.version); "--feature-level"; "1"] in
-			let args =
-				match gen.gentry_point with
-				| Some (name,_,_) ->
-					let name = if gen.gcon.debug then name ^ "-Debug" else name in
-					args@["--out"; gen.gcon.file ^ "/bin/" ^ name]
-				| _ ->
-					args
-			in
-			print_endline (cmd ^ " " ^ (String.concat " " args));
-			if gen.gcon.run_command_args cmd args <> 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

+ 0 - 2723
src/generators/genjava.ml

@@ -1,2723 +0,0 @@
-(*
-	The Haxe Compiler
-	Copyright (C) 2005-2019  Haxe Foundation
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *)
-open Extlib_leftovers
-open Globals
-open JData
-open Unix
-open Ast
-open Common
-open Type
-open Codegen
-open Gencommon
-open Gencommon.SourceWriter
-open Printf
-open Option
-open ExtString
-
-let is_boxed_type t = match follow t with
-	| TInst ({ cl_path = (["java";"lang"], "Boolean") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Double") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Integer") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Byte") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Short") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Character") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Float") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Long") }, []) -> true
-	| _ -> false
-
-let is_boxed_of_t boxed_t orig_t = match follow boxed_t, follow orig_t with
-	| TInst ({ cl_path = (["java";"lang"], "Boolean") }, []),
-	  TAbstract({ a_path = ([],"Bool") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Double") }, []),
-	  TAbstract({ a_path = ([],"Float") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Integer") }, []),
-	  TAbstract({ a_path = ([],"Int") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Byte") }, []),
-	  TAbstract({ a_path = (["java"],"Int8") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Short") }, []),
-	  TAbstract({ a_path = (["java"],"Int16") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Character") }, []),
-	  TAbstract({ a_path = (["java"],"Char16") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Float") }, []),
-	  TAbstract({ a_path = ([],"Single") }, [])
-	| TInst ({ cl_path = (["java";"lang"], "Long") }, []),
-	  TAbstract({ a_path = (["java"],"Int64") }, []) ->
-		true
-	| _ -> false
-
-let is_boxed_int_type boxed_t = match follow boxed_t with
-	| TInst ({ cl_path = (["java";"lang"], ("Integer"|"Byte"|"Short"|"Long")) }, []) ->
-		true
-	| _ -> false
-
-let is_int64_type t = match follow t with
-	| TAbstract ({ a_path = (["java"], ("Int64")) }, []) ->
-		true
-	| _ -> false
-
-let is_boxed_int64_type t = match follow t with
-	| TInst ({ cl_path = (["java";"lang"], ("Long")) }, []) ->
-		true
-	| _ -> false
-
-let is_int_type t = match follow t with
-	| TAbstract ({ a_path = ([], ("Int")) }, [])
-	| TAbstract ({ a_path = (["java"], ("Int8" | "Int16" | "Int64")) }, []) ->
-		true
-	| _ -> false
-
-let is_boxed_float_type boxed_t = match follow boxed_t with
-	| TInst ({ cl_path = (["java";"lang"], ("Double"|"Float")) }, []) ->
-		true
-	| _ -> false
-
-let is_float_type t = match follow t with
-	| TAbstract ({ a_path = ([], ("Float"|"Single")) }, []) ->
-		true
-	| _ -> false
-
-let is_boxed_number t = match follow t with
-	| TInst ({ cl_path = (["java";"lang"], ("Float"|"Double"|"Integer"|"Byte"|"Short"|"Long")) }, []) ->
-		true
-	| _ ->
-		false
-
-let is_unboxed_number t = match follow t with
-	| TAbstract ({ a_path = ([], ("Float"|"Single"|"Int")) }, [])
-	| TAbstract ({ a_path = (["java"], ("Int8" | "Int16" | "Int64")) }, []) ->
-		true
-	| _ -> false
-
-let rec t_has_type_param t = match follow t with
-	| TInst({ cl_kind = KTypeParameter _ }, []) -> true
-	| TEnum(_, params)
-	| TAbstract(_, params)
-	| TInst(_, params) -> List.exists t_has_type_param params
-	| TFun(f,ret) -> t_has_type_param ret || List.exists (fun (_,_,t) -> t_has_type_param t) f
-	| _ -> false
-
-let is_dynamic gen t =
-	match follow (gen.greal_type t) with
-		| TDynamic _ -> true
-		| _ -> false
-
-let is_type_param t = ExtType.is_type_param (follow t)
-
-let rec t_has_type_param_shallow last t = match follow t with
-	| TInst({ cl_kind = KTypeParameter _ }, []) -> true
-	| TEnum(_, params)
-	| TAbstract(_, params)
-	| TInst(_, params) when not last -> List.exists (t_has_type_param_shallow true) params
-	| TFun(f,ret) when not last -> t_has_type_param_shallow true ret	|| List.exists (fun (_,_,t) -> t_has_type_param_shallow true t) f
-	| _ -> false
-
-let rec replace_type_param t = match follow t with
-	| TInst({ cl_kind = KTypeParameter _ }, []) -> t_dynamic
-	| TEnum(e, params) -> TEnum(e, List.map replace_type_param params)
-	| TAbstract(a, params) -> TAbstract(a, List.map replace_type_param params)
-	| TInst(cl, params) -> TInst(cl, List.map replace_type_param params)
-	| _ -> t
-
-let in_runtime_class gen =
-	match gen.gcurrent_class with
-	| Some { cl_path = ["haxe";"lang"],"Runtime"} -> true
-	| _ -> false
-
-let is_java_basic_type t =
-	match follow t with
-		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
-		| TInst( { cl_path = (["haxe"], "Int64") }, [] )
-		| TAbstract( { a_path = (["java"], ("Int8" | "Int16" | "Char16" | "Int64")) }, [] )
-		| TAbstract( { a_path =	([], ("Int"|"Float"|"Bool"|"Single")) }, [] ) ->
-			true
-		| _ -> false
-
-let is_bool t =
-	match follow t with
-		| TAbstract ({ a_path = ([], "Bool") },[]) ->
-			true
-		| _ -> false
-
-let like_bool t =
-	match follow t with
-		| TAbstract ({ a_path = ([], "Bool") },[])
-		| TAbstract ({ a_path = (["java";"lang"],"Boolean") },[])
-		| TInst ({ cl_path = (["java";"lang"],"Boolean") },[]) ->
-			true
-		| _ -> false
-
-let is_int_float gen t =
-	match follow (gen.greal_type t) with
-		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
-		| TAbstract( { a_path =	([], "Int") }, [] )
-		| TAbstract( { a_path =	([], "Float") }, [] ) ->
-			true
-		| (TAbstract _ as t) when like_float t && not (like_i64 t)-> true
-		| _ -> false
-
-let parse_explicit_iface =
-	let regex = Str.regexp "\\." in
-	let parse_explicit_iface str =
-		let split = Str.split regex str in
-		let rec get_iface split pack =
-			match split with
-				| clname :: fn_name :: [] -> fn_name, (List.rev pack, clname)
-				| pack_piece :: tl -> get_iface tl (pack_piece :: pack)
-				| _ -> die "" __LOC__
-		in
-		get_iface split []
-	in parse_explicit_iface
-
-let is_cl t = match follow t with
-	| TInst({ cl_path = ["java";"lang"],"Class" },_)
-	| TAbstract({ a_path = [], ("Class"|"Enum") },_) -> true
-	| TAnon(a) when is_some (anon_class t) -> true
-	| _ -> false
-
-let mk_cast_if_needed t_to e =
-	if type_iseq t_to e.etype then
-		e
-	else
-		mk_cast t_to e
-
-(* ******************************************* *)
-(* JavaSpecificESynf *)
-(* ******************************************* *)
-(*
-	Some Java-specific syntax filters that must run before ExpressionUnwrap
-
-	dependencies:
-		It must run before ExprUnwrap, as it may not return valid Expr/Statement expressions
-		It must run before ClassInstance, as it will detect expressions that need unchanged TTypeExpr
-		It must run after CastDetect, as it changes casts
-		It must run after TryCatchWrapper, to change Std.is() calls inside there
-*)
-module JavaSpecificESynf =
-struct
-	let name = "java_specific_e"
-	let priority = solve_deps name [ DBefore ExpressionUnwrap.priority; DBefore ClassInstance.priority; DAfter CastDetect.priority]
-
-	let get_cl_from_t t =
-		match follow t with
-			| TInst(cl,_) -> cl
-			| _ -> die "" __LOC__
-
-	let configure gen runtime_cl =
-		let basic = gen.gcon.basic in
-		let float_cl = get_cl ( get_type gen (["java";"lang"], "Double")) in
-		let i8_md  = ( get_type gen (["java";"lang"], "Byte")) in
-		let i16_md	= ( get_type gen (["java";"lang"], "Short")) in
-		let i64_md	= ( get_type gen (["java";"lang"], "Long")) in
-		let c16_md	= ( get_type gen (["java";"lang"], "Character")) in
-		let f_md	= ( get_type gen (["java";"lang"], "Float")) in
-		let bool_md = get_type gen (["java";"lang"], "Boolean") in
-
-		let rec run e =
-			match e.eexpr with
-				(* Math changes *)
-				| TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "NaN" }) ) ->
-					mk_static_field_access_infer float_cl "NaN" e.epos []
-				| TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "NEGATIVE_INFINITY" }) ) ->
-					mk_static_field_access_infer float_cl "NEGATIVE_INFINITY" e.epos []
-				| TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "POSITIVE_INFINITY" }) ) ->
-					mk_static_field_access_infer float_cl "POSITIVE_INFINITY" e.epos []
-				| TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "isNaN"}) ) ->
-					mk_static_field_access_infer float_cl "isNaN" e.epos []
-				| TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("ffloor" as f) }) ) } as fe), p)
-				| TCall( ({ eexpr = TField( (_ as ef), FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = ("fceil" as f) }) ) } as fe), p) ->
-						Type.map_expr run { e with eexpr = TCall({ fe with eexpr = TField(ef, FDynamic (String.sub f 1 (String.length f - 1)))	}, p) }
-				| TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "floor" }) ) }, _)
-				| TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "round" }) ) }, _)
-				| TCall( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "ceil" }) ) }, _) ->
-						mk_cast basic.tint (Type.map_expr run { e with etype = basic.tfloat })
-				| TCall( ( { eexpr = TField( _, FStatic({ cl_path = (["java";"lang"], "Math") }, { cf_name = "isFinite" }) ) } as efield ), [v]) ->
-					{ e with eexpr = TCall( mk_static_field_access_infer runtime_cl "isFinite" efield.epos [], [run v] ) }
-				(* end of math changes *)
-
-				(* Std.is() *)
-				| TCall(
-						{ eexpr = TField( _, FStatic({ cl_path = ([], "Std") }, { cf_name = ("is" | "isOfType") })) },
-						[ obj; { eexpr = TTypeExpr(md) } ]
-					) ->
-					let mk_is is_basic obj md =
-						let obj = if is_basic then mk_cast t_dynamic obj else obj in
-						{ e with eexpr = TCall( { eexpr = TIdent "__is__"; etype = t_dynamic; epos = e.epos }, [
-							run obj;
-							{ eexpr = TTypeExpr md; etype = t_dynamic (* this is after all a syntax filter *); epos = e.epos }
-						] ) }
-					in
-					(match follow_module follow md with
-						| TAbstractDecl({ a_path = ([], "Float") }) ->
-							{
-								eexpr = TCall(
-									mk_static_field_access_infer runtime_cl "isDouble" e.epos [],
-									[ run obj ]
-								);
-								etype = basic.tbool;
-								epos = e.epos
-							}
-						| TAbstractDecl{ a_path = ([], "Int") } ->
-							{
-								eexpr = TCall(
-									mk_static_field_access_infer runtime_cl "isInt" e.epos [],
-									[ run obj ]
-								);
-								etype = basic.tbool;
-								epos = e.epos
-							}
-						| TAbstractDecl{ a_path = ([], "Bool") } ->
-							mk_is true obj bool_md
-						| TAbstractDecl{ a_path = ([], "Single") } ->
-							mk_is true obj f_md
-						| TAbstractDecl{ a_path = (["java"], "Int8") } ->
-							mk_is true obj i8_md
-						| TAbstractDecl{ a_path = (["java"], "Int16") } ->
-							mk_is true obj i16_md
-						| TAbstractDecl{ a_path = (["java"], "Char16") } ->
-							mk_is true obj c16_md
-						| TAbstractDecl{ a_path = (["java"], "Int64") } ->
-							mk_is true obj i64_md
-						| TClassDecl{ cl_path = (["haxe"], "Int64") } ->
-							mk_is true obj i64_md
-						| TAbstractDecl{ a_path = ([], "Dynamic") }
-						| TClassDecl{ cl_path = ([], "Dynamic") } when not (is_nullable obj.etype) ->
-							(match obj.eexpr with
-								| TLocal _ | TConst _ -> { e with eexpr = TConst(TBool true) }
-								| _ -> { e with eexpr = TBlock([run obj; { e with eexpr = TConst(TBool true) }]) }
-							)
-						| _ ->
-							if not (is_java_basic_type obj.etype) then
-								try
-									Type.unify obj.etype (type_of_module_type md);
-									mk_is false obj md
-								with Unify_error _ -> e
-							else e
-					)
-				(* end Std.is() *)
-				| _ -> Type.map_expr run e
-		in
-		gen.gsyntax_filters#add name (PCustom priority) run
-
-end;;
-
-
-(* ******************************************* *)
-(* JavaSpecificSynf *)
-(* ******************************************* *)
-(*
-	Some Java-specific syntax filters that can run after ExprUnwrap
-
-	dependencies:
-		Runs after ExprUnwarp
-*)
-module JavaSpecificSynf =
-struct
-	let name = "java_specific"
-	let priority = solve_deps name [ DAfter ExpressionUnwrap.priority; DAfter ObjectDeclMap.priority; DAfter ArrayDeclSynf.priority; DBefore IntDivisionSynf.priority ]
-
-	let java_hash s =
-		let high_surrogate c = (c lsr 10) + 0xD7C0 in
-		let low_surrogate c = (c land 0x3FF) lor 0xDC00 in
-		let h = ref Int32.zero in
-		let thirtyone = Int32.of_int 31 in
-		(try
-			UTF8.validate s;
-			UTF8.iter (fun c ->
-				let c = (UCharExt.code c) in
-				if c > 0xFFFF then
-					(h := Int32.add (Int32.mul thirtyone !h)
-						(Int32.of_int (high_surrogate c));
-					h := Int32.add (Int32.mul thirtyone !h)
-						(Int32.of_int (low_surrogate c)))
-				else
-					h := Int32.add (Int32.mul thirtyone !h)
-						(Int32.of_int c)
-				) s
-		with UTF8.Malformed_code ->
-			String.iter (fun c ->
-				h := Int32.add (Int32.mul thirtyone !h)
-					(Int32.of_int (Char.code c))) s
-		);
-		!h
-
-	let rec is_final_return_expr is_switch e =
-		let is_final_return_expr = is_final_return_expr is_switch in
-		match e.eexpr with
-			| TReturn _
-			| TThrow _ -> true
-			(* this is hack to not use 'break' on switch cases *)
-			| TIdent "__fallback__" when is_switch -> true
-			| TMeta ((Meta.LoopLabel,_,_), { eexpr = TBreak }) -> true
-			| TParenthesis p | TMeta (_,p) -> is_final_return_expr p
-			| TBlock bl -> is_final_return_block is_switch bl
-			| TSwitch (_, el_e_l, edef) ->
-				List.for_all (fun (_,e) -> is_final_return_expr e) el_e_l && Option.map_default is_final_return_expr false edef
-			| TIf (_,eif, Some eelse) ->
-				is_final_return_expr eif && is_final_return_expr eelse
-			| TFor (_,_,e) ->
-				is_final_return_expr e
-			| TWhile (_,e,_) ->
-				is_final_return_expr e
-			| TFunction tf ->
-				is_final_return_expr tf.tf_expr
-			| TTry (e, ve_l) ->
-				is_final_return_expr e && List.for_all (fun (_,e) -> is_final_return_expr e) ve_l
-			| _ -> false
-
-	and is_final_return_block is_switch el =
-		match el with
-			| [] -> false
-			| final :: [] -> is_final_return_expr is_switch final
-			| hd :: tl -> is_final_return_block is_switch tl
-
-	let rec is_null e = match e.eexpr with
-		| TConst(TNull) -> true
-		| TParenthesis(e)
-		| TMeta(_,e) -> is_null e
-		| _ -> false
-
-	let rec is_equatable gen t =
-		match follow t with
-			| TInst(cl,_) ->
-				if cl.cl_path = (["haxe";"lang"], "IEquatable") then
-					true
-				else
-					List.exists (fun (cl,p) -> is_equatable gen (TInst(cl,p))) cl.cl_implements
-						|| (match cl.cl_super with | Some(cl,p) -> is_equatable gen (TInst(cl,p)) | None -> false)
-			| _ -> false
-
-	(*
-		Changing string switch
-		will take an expression like
-		switch(str)
-		{
-			case "a":
-			case "b":
-		}
-
-		and modify it to:
-		{
-			var execute_def = true;
-			switch(str == null ? 0 : str.hashCode())
-			{
-				case (hashcode of a):
-					if (str == "a")
-					{
-						execute_def = false;
-						..code here
-					} //else if (str == otherVariableWithSameHashCode) {
-						...
-					}
-				...
-			}
-			if (execute_def)
-			{
-				..default code
-			}
-		}
-
-		this might actually be slower in some cases than a if/else approach, but it scales well and as a bonus,
-		hashCode in java are cached, so we only have the performance hit once to cache it.
-	*)
-	let change_string_switch gen eswitch e1 ecases edefault =
-		let basic = gen.gcon.basic in
-		let is_final_ret = is_final_return_expr false eswitch in
-
-		let has_default = is_some edefault in
-		let block = ref [] in
-		let local = match e1.eexpr with
-			| TLocal _ -> e1
-			| _ ->
-				let var = mk_temp "svar" e1.etype in
-				let added = { e1 with eexpr = TVar(var, Some(e1)); etype = basic.tvoid } in
-				let local = mk_local var e1.epos in
-				block := added :: !block;
-				local
-		in
-		let execute_def_var = mk_temp "executeDef" gen.gcon.basic.tbool in
-		let execute_def = mk_local execute_def_var e1.epos in
-		let execute_def_set = { eexpr = TBinop(Ast.OpAssign, execute_def, { eexpr = TConst(TBool false); etype = basic.tbool; epos = e1.epos }); etype = basic.tbool; epos = e1.epos } in
-
-		let hash_cache = ref None in
-
-		let local_hashcode = ref { local with
-			eexpr = TCall({ local with
-				eexpr = TField(local, FDynamic "hashCode");
-				etype = TFun([], basic.tint);
-			}, []);
-			etype = basic.tint
-		} in
-
-		let get_hash_cache () =
-			match !hash_cache with
-				| Some c -> c
-				| None ->
-					let var = mk_temp "hash" basic.tint in
-					let cond = !local_hashcode in
-					block := { eexpr = TVar(var, Some cond); etype = basic.tvoid; epos = local.epos } :: !block;
-					let local = mk_local var local.epos in
-					local_hashcode := local;
-					hash_cache := Some local;
-					local
-		in
-
-		let has_case = ref false in
-		(* first we need to reorder all cases so all collisions are close to each other *)
-
-		let get_str e = match e.eexpr with | TConst(TString s) -> s | _ -> die "" __LOC__ in
-		let has_conflict = ref false in
-
-		let rec reorder_cases unordered ordered =
-			match unordered with
-				| [] -> ordered
-				| (el, e) :: tl ->
-					let current = Hashtbl.create 1 in
-					List.iter (fun e ->
-						let str = get_str e in
-						let hash = java_hash str in
-						Hashtbl.add current hash true
-					) el;
-
-					let rec extract_fields cases found_cases ret_cases =
-						match cases with
-							| [] -> found_cases, ret_cases
-							| (el, e) :: tl ->
-								if List.exists (fun e -> Hashtbl.mem current (java_hash (get_str e)) ) el then begin
-									has_conflict := true;
-									List.iter (fun e -> Hashtbl.add current (java_hash (get_str e)) true) el;
-									extract_fields tl ( (el, e) :: found_cases ) ret_cases
-								end else
-									extract_fields tl found_cases ( (el, e) :: ret_cases )
-					in
-					let found, remaining = extract_fields tl [] [] in
-					let ret = if found <> [] then
-						let ret = List.sort (fun (e1,_) (e2,_) -> compare (List.length e2) (List.length e1) ) ( (el, e) :: found ) in
-						let rec loop ret acc =
-							match ret with
-								| (el, e) :: ( (_,_) :: _ as tl ) -> loop tl ( (true, el, e) :: acc )
-								| (el, e) :: [] -> ( (false, el, e) :: acc )
-								| _ -> die "" __LOC__
-						in
-						List.rev (loop ret [])
-					else
-						(false, el, e) :: []
-					in
-
-					reorder_cases remaining (ordered @ ret)
-		in
-
-		let already_in_cases = Hashtbl.create 0 in
-		let change_case (has_fallback, el, e) =
-			let conds, el = List.fold_left (fun (conds,el) e ->
-				has_case := true;
-				match e.eexpr with
-					| TConst(TString s) ->
-						let hashed = java_hash s in
-						let equals_test = {
-							eexpr = TCall({ e with eexpr = TField(local, FDynamic "equals"); etype = TFun(["obj",false,t_dynamic],basic.tbool) }, [ e ]);
-							etype = basic.tbool;
-							epos = e.epos
-						} in
-
-						let hashed_expr = { eexpr = TConst(TInt hashed); etype = basic.tint; epos = e.epos } in
-						let hashed_exprs = if !has_conflict then begin
-							if Hashtbl.mem already_in_cases hashed then
-								el
-							else begin
-								Hashtbl.add already_in_cases hashed true;
-								hashed_expr :: el
-							end
-						end else hashed_expr :: el in
-
-						let conds = match conds with
-							| None -> equals_test
-							| Some c ->
-								(*
-									if there is more than one case, we should test first if hash equals to the one specified.
-									This way we can save a heavier string compare
-								*)
-								let equals_test = mk_paren {
-									eexpr = TBinop(Ast.OpBoolAnd, { eexpr = TBinop(Ast.OpEq, get_hash_cache(), hashed_expr); etype = basic.tbool; epos = e.epos }, equals_test);
-									etype = basic.tbool;
-									epos = e.epos;
-								} in
-
-								{ eexpr = TBinop(Ast.OpBoolOr, equals_test, c); etype = basic.tbool; epos = e1.epos }
-						in
-
-						Some conds, hashed_exprs
-					| _ -> die "" __LOC__
-			) (None,[]) el in
-			let e = if has_default then Type.concat execute_def_set e else e in
-			let e = if !has_conflict then Type.concat e { e with eexpr = TBreak; etype = basic.tvoid } else e in
-			let e = {
-				eexpr = TIf(get conds, e, None);
-				etype = basic.tvoid;
-				epos = e.epos
-			} in
-
-			let e = if has_fallback then { e with eexpr = TBlock([ e; mk (TIdent "__fallback__") t_dynamic e.epos]) } else e in
-
-			(el, e)
-		in
-
-		let is_not_null_check = mk (TBinop (OpNotEq, local, { local with eexpr = TConst TNull })) basic.tbool local.epos in
-		let if_not_null e = { e with eexpr = TIf (is_not_null_check, e, None) } in
-		let switch = if_not_null { eswitch with
-			eexpr = TSwitch(!local_hashcode, List.map change_case (reorder_cases ecases []), None);
-		} in
-		(if !has_case then begin
-			(if has_default then block := { e1 with eexpr = TVar(execute_def_var, Some({ e1 with eexpr = TConst(TBool true); etype = basic.tbool })); etype = basic.tvoid } :: !block);
-			block := switch :: !block
-		end);
-		(match edefault with
-			| None -> ()
-			| Some edef when not !has_case ->
-				block := edef :: !block
-			| Some edef ->
-				let eelse = if is_final_ret then Some { eexpr = TThrow { eexpr = TConst(TNull); etype = t_dynamic; epos = edef.epos }; etype = basic.tvoid; epos = edef.epos } else None in
-				block := { edef with eexpr = TIf(execute_def, edef, eelse); etype = basic.tvoid } :: !block
-		);
-		{ eswitch with eexpr = TBlock(List.rev !block) }
-
-
-	let get_cl_from_t t =
-		match follow t with
-		| TInst(cl,_) -> cl
-		| _ -> die "" __LOC__
-
-	let configure gen runtime_cl =
-		let cl_boolean = get_cl (get_type gen (["java";"lang"],"Boolean")) in
-		let cl_number = get_cl (get_type gen (["java";"lang"],"Number")) in
-
-		(if java_hash "Testing string hashCode implementation from haXe" <> (Int32.of_int 545883604) then die "" __LOC__);
-		let basic = gen.gcon.basic in
-		let tbyte = mt_to_t_dyn ( get_type gen (["java"], "Int8") ) in
-		let tshort = mt_to_t_dyn ( get_type gen (["java"], "Int16") ) in
-		let tsingle = mt_to_t_dyn ( get_type gen ([], "Single") ) in
-		let ti64 = mt_to_t_dyn ( get_type gen (["java"], "Int64") ) in
-		let string_ext = get_cl ( get_type gen (["haxe";"lang"], "StringExt")) in
-		let fast_cast = Common.defined gen.gcon Define.FastCast in
-
-		let get_unboxed_from_boxed boxed_t =
-			match boxed_t with
-				| TInst( ({ cl_path = (["java";"lang"],name) } as cl), [] ) -> (match name with
-					| "Double" ->
-						cl, basic.tfloat
-					| "Integer" ->
-						cl, basic.tint
-					| "Byte" ->
-						cl, tbyte
-					| "Short" ->
-						cl, tshort
-					| "Float" ->
-						cl, tsingle
-					| "Long" ->
-						cl, ti64
-					| _ ->
-						die "" __LOC__)
-				| _ -> die "" __LOC__
-		in
-
-		let mk_valueof_call boxed_t expr =
-			let box_cl, unboxed_t = get_unboxed_from_boxed boxed_t in
-			let fn = TFun(["param1",false,unboxed_t],boxed_t) in
-			{
-				eexpr = TCall(mk_static_field_access box_cl "valueOf" fn expr.epos, [mk_cast_if_needed unboxed_t expr]);
-				etype = boxed_t;
-				epos = expr.epos;
-			}
-		in
-
-		let mk_unbox unboxed_t boxed_e =
-			if is_int64_type unboxed_t then
-				{
-					eexpr = TCall(
-						mk_static_field_access_infer runtime_cl "getInt64FromNumber" boxed_e.epos [],
-						[ boxed_e ]
-					);
-					etype = ti64;
-					epos = boxed_e.epos
-				}
-			else if is_int_type unboxed_t then
-				mk_cast_if_needed unboxed_t {
-					eexpr = TCall(
-						mk_static_field_access_infer runtime_cl "getIntFromNumber" boxed_e.epos [],
-						[ boxed_e ]
-					);
-					etype = basic.tint;
-					epos = boxed_e.epos
-				}
-			else
-				mk_cast_if_needed unboxed_t {
-					eexpr = TCall(
-						mk_static_field_access_infer runtime_cl "getFloatFromNumber" boxed_e.epos [],
-						[ boxed_e ]
-					);
-					etype = basic.tfloat;
-					epos = boxed_e.epos
-				}
-		in
-
-		let mk_dyn_box boxed_t expr =
-			let name = match boxed_t with
-				| TInst({ cl_path = (["java";"lang"],"Integer") },[]) ->
-					"numToInteger"
-				| TInst({ cl_path = (["java";"lang"],"Double") },[]) ->
-					"numToDouble"
-				| TInst({ cl_path = (["java";"lang"],"Float") },[]) ->
-					"numToFloat"
-				| TInst({ cl_path = (["java";"lang"],"Byte") },[]) ->
-					"numToByte"
-				| TInst({ cl_path = (["java";"lang"],"Long") },[]) ->
-					"numToLong"
-				| TInst({ cl_path = (["java";"lang"],"Short") },[]) ->
-					"numToShort"
-				| _ -> gen.gcon.error ("Invalid boxed type " ^ (debug_type boxed_t)) expr.epos; die "" __LOC__
-			in
-			{
-				eexpr = TCall(
-					mk_static_field_access_infer runtime_cl name expr.epos [],
-					[ mk_cast (TInst(cl_number,[])) expr ]
-				);
-				etype = boxed_t;
-				epos = expr.epos
-			}
-		in
-
-		let rec run e =
-			match e.eexpr with
-				(* for new NativeArray<T> issues *)
-				| TNew(({ cl_path = (["java"], "NativeArray") } as cl), [t], el) when is_type_param t ->
-					mk_cast (TInst(cl,[t])) (mk_cast t_dynamic ({ e with eexpr = TNew(cl, [t_empty], List.map run el) }))
-
-				(* Std.int() *)
-				| TCall(
-						{ eexpr = TField( _, FStatic({ cl_path = ([], "Std") }, { cf_name = "int" })) },
-						[obj]
-					) ->
-					run (mk_cast basic.tint obj)
-				(* end Std.int() *)
-
-				| TField( ef, FInstance({ cl_path = ([], "String") }, _, { cf_name = "length" }) ) ->
-					{ e with eexpr = TCall(Type.map_expr run e, []) }
-				| TField( ef, field ) when field_name field = "length" && is_string ef.etype ->
-					{ e with eexpr = TCall(Type.map_expr run e, []) }
-				| TCall( ( { eexpr = TField(ef, field) } as efield ), args ) when is_string ef.etype && String.get (field_name field) 0 = '_' ->
-					let field = field_name field in
-					{ e with eexpr = TCall({ efield with eexpr = TField(run ef, FDynamic (String.sub field 1 ( (String.length field) - 1)) )}, List.map run args) }
-				| TCall( ( { eexpr = TField(ef, FInstance({ cl_path = [], "String" }, _, field )) } as efield ), args ) ->
-					let field = field.cf_name in
-					(match field with
-						| "charAt" | "charCodeAt" | "split" | "indexOf"
-						| "lastIndexOf" | "substring" | "substr" ->
-							{ e with eexpr = TCall(mk_static_field_access_infer string_ext field e.epos [], [run ef] @ (List.map run args)) }
-						| _ ->
-							{ e with eexpr = TCall(run efield, List.map run args) }
-					)
-
-				| TCast(expr, _) when is_boxed_number (gen.greal_type expr.etype) && is_unboxed_number (gen.greal_type e.etype) ->
-					let to_t = gen.greal_type e.etype in
-					mk_unbox to_t (run expr)
-
-				| TCast(expr, md) when is_boxed_number (gen.greal_type e.etype) ->
-					let to_t = gen.greal_type e.etype in
-					let from_t = gen.greal_type expr.etype in
-					let ret = if is_unboxed_number from_t then
-							mk_valueof_call to_t (run expr)
-						else if is_boxed_number from_t then
-							if type_iseq from_t to_t then begin
-								(* special case for when the expression is null, as we sometimes need to give *)
-								(* a little help to Java's typer *)
-								if is_null expr then
-									{ e with eexpr = TCast(run expr, md) }
-								else
-									run expr
-							end else
-								mk_dyn_box (gen.greal_type e.etype) (run expr)
-						else begin
-							if in_runtime_class gen then
-								mk_cast e.etype (run expr)
-							else
-								mk_dyn_box (gen.greal_type e.etype) (run expr)
-						end
-					in
-					ret
-
-				| TCast(expr, _) when is_bool e.etype ->
-					{
-						eexpr = TCall(
-							mk_static_field_access_infer runtime_cl "toBool" expr.epos [],
-							[ mk_cast_if_needed (TInst(cl_boolean,[])) (run expr) ]
-						);
-						etype = basic.tbool;
-						epos = e.epos
-					}
-
-				| TCast(expr, _) when is_int_float gen e.etype && is_dynamic gen expr.etype ->
-					let needs_cast = match gen.gfollow#run_f e.etype with
-						| TInst _ -> false
-						| _ -> true
-					in
-
-					let fun_name = if like_int e.etype then "toInt" else "toDouble" in
-
-					let ret = {
-						eexpr = TCall(
-							mk_static_field_access_infer runtime_cl fun_name expr.epos [],
-							[ run expr ]
-						);
-						etype = if fun_name = "toDouble" then basic.tfloat else basic.tint;
-						epos = expr.epos
-					} in
-
-					if needs_cast then mk_cast e.etype ret else ret
-
-				| TCast(expr, _) when like_i64 e.etype && is_dynamic gen expr.etype ->
-					{
-						eexpr = TCall(
-							mk_static_field_access_infer runtime_cl "toLong" expr.epos [],
-							[ run expr ]
-						);
-						etype = ti64;
-						epos = expr.epos
-					}
-
-				| TCast(expr, Some(TClassDecl cls)) when fast_cast && cls == null_class ->
-					{ e with eexpr = TCast(run expr, Some(TClassDecl null_class)) }
-
-				| TBinop( (Ast.OpAssignOp OpAdd as op), e1, e2)
-				| TBinop( (Ast.OpAdd as op), e1, e2) when not fast_cast && (is_string e.etype || is_string e1.etype || is_string e2.etype) ->
-						let is_assign = match op with Ast.OpAssignOp _ -> true | _ -> false in
-						let mk_to_string e = { e with eexpr = TCall( mk_static_field_access_infer runtime_cl "toString" e.epos [], [run e] ); etype = gen.gcon.basic.tstring	} in
-						let check_cast e = match gen.greal_type e.etype with
-							| TDynamic _
-							| TAbstract({ a_path = ([], "Float") }, [])
-							| TAbstract({ a_path = ([], "Single") }, []) ->
-									mk_to_string e
-							| _ -> run e
-						in
-
-						{ e with eexpr = TBinop(op, (if is_assign then run e1 else check_cast e1), check_cast e2) }
-				| TCast(expr, _) when is_string e.etype ->
-					{ e with eexpr = TCall( mk_static_field_access_infer runtime_cl "toString" expr.epos [], [run expr] ) }
-
-				| TSwitch(cond, ecases, edefault) when is_string cond.etype ->
-					(*let change_string_switch gen eswitch e1 ecases edefault =*)
-					change_string_switch gen e (run cond) (List.map (fun (el,e) -> (el, run e)) ecases) (Option.map run edefault)
-
-				| TBinop( (Ast.OpNotEq as op), e1, e2)
-				| TBinop( (Ast.OpEq as op), e1, e2) when not (is_null e2 || is_null e1) && (is_string e1.etype || is_string e2.etype || is_equatable gen e1.etype || is_equatable gen e2.etype) ->
-					let static = mk_static_field_access_infer (runtime_cl) "valEq" e1.epos [] in
-					let eret = { eexpr = TCall(static, [run e1; run e2]); etype = gen.gcon.basic.tbool; epos=e.epos } in
-					if op = Ast.OpNotEq then { eret with eexpr = TUnop(Ast.Not, Ast.Prefix, eret) } else eret
-
-				| TBinop( (Ast.OpNotEq | Ast.OpEq as op), e1, e2) when is_cl e1.etype && is_cl e2.etype ->
-					{ e with eexpr = TBinop(op, mk_cast t_empty (run e1), mk_cast t_empty (run e2)) }
-				| _ -> Type.map_expr run e
-		in
-		gen.gsyntax_filters#add name (PCustom priority) run
-end;;
-
-
-(* ******************************************* *)
-(* handle @:throws *)
-(* ******************************************* *)
-let rec is_checked_exc cl =
-	match cl.cl_path with
-		| ["java";"lang"],"RuntimeException" ->
-			false
-		| ["java";"lang"],"Throwable" ->
-			true
-		| _ -> match cl.cl_super with
-			| None -> false
-			| Some(c,_) -> is_checked_exc c
-
-let rec cls_any_super cl supers =
-	PMap.mem cl.cl_path supers || match cl.cl_super with
-		| None -> false
-		| Some(c,_) -> cls_any_super c supers
-
-let rec handle_throws gen cf =
-	List.iter (handle_throws gen) cf.cf_overloads;
-	match cf.cf_expr with
-	| Some ({ eexpr = TFunction(tf) } as e)  ->
-		let rec collect_throws acc = function
-			| (Meta.Throws, [Ast.EConst (Ast.String(path,_)), _],_) :: meta -> (try
-				collect_throws (get_cl ( get_type gen (parse_path path)) :: acc) meta
-			with | Not_found | TypeNotFound _ ->
-				collect_throws acc meta)
-			| [] ->
-				acc
-			| _ :: meta ->
-				collect_throws acc meta
-		in
-		let cf_throws = collect_throws [] cf.cf_meta in
-		let throws = ref (List.fold_left (fun map cl ->
-			PMap.add cl.cl_path cl map
-		) PMap.empty cf_throws) in
-		let rec iter e = match e.eexpr with
-			| TTry(etry,ecatches) ->
-				let old = !throws in
-				let needs_check_block = ref true in
-				List.iter (fun (v,e) ->
-					Type.iter iter e;
-					match follow (run_follow gen v.v_type) with
-						| TInst({ cl_path = ["java";"lang"],"Throwable" },_)
-						| TDynamic _ ->
-							needs_check_block := false
-						| TInst(c,_) when is_checked_exc c ->
-							throws := PMap.add c.cl_path c !throws
-						| _ ->()
-				) ecatches;
-				if !needs_check_block then Type.iter iter etry;
-				throws := old
-			| TField(e, (FInstance(_,_,f) | FStatic(_,f) | FClosure(_,f))) ->
-				let tdefs = collect_throws [] f.cf_meta in
-				if tdefs <> [] && not (List.for_all (fun c -> cls_any_super c !throws) tdefs) then
-					raise Exit;
-				Type.iter iter e
-			| TThrow e -> (match follow (run_follow gen e.etype) with
-				| TInst(c,_) when is_checked_exc c && not (cls_any_super c !throws) ->
-					raise Exit
-				| _ -> iter e)
-			| _ -> Type.iter iter e
-		in
-		(try
-			Type.iter iter e
-		with | Exit -> (* needs typed exception to be caught *)
-			let throwable = get_cl (get_type gen (["java";"lang"],"Throwable")) in
-			let cast_cl = get_cl (get_type gen (["java";"lang"],"RuntimeException")) in
-			let catch_var = alloc_var "typedException" (TInst(throwable,[])) in
-			let rethrow = mk_local catch_var e.epos in
-			let hx_exception = get_cl (get_type gen (["haxe"], "Exception")) in
-			let wrap_static = mk_static_field_access (hx_exception) "thrown" (TFun([("obj",false,t_dynamic)], t_dynamic)) rethrow.epos in
-			let thrown_value = mk_cast (TInst(cast_cl,[])) { rethrow with eexpr = TCall(wrap_static, [rethrow]) } in
-			let wrapped = { rethrow with eexpr = TThrow thrown_value; } in
-			let map_throws cl =
-				let var = alloc_var "typedException" (TInst(cl,List.map (fun _ -> t_dynamic) cl.cl_params)) in
-				var, { tf.tf_expr with eexpr = TThrow (mk_local var e.epos) }
-			in
-			cf.cf_expr <- Some { e with
-				eexpr = TFunction({ tf with
-					tf_expr = mk_block { tf.tf_expr with eexpr = TTry(tf.tf_expr, List.map (map_throws) cf_throws @ [catch_var, wrapped]) }
-				})
-			})
-	| _ -> ()
-
-
-let connecting_string = "?" (* ? see list here http://www.fileformat.info/info/unicode/category/index.htm and here for C# http://msdn.microsoft.com/en-us/library/aa664670.aspx *)
-let default_package = "java"
-let strict_mode = ref false (* strict mode is so we can check for unexpected information *)
-
-(* reserved java words *)
-let reserved = let res = Hashtbl.create 120 in
-	List.iter (fun lst -> Hashtbl.add res lst ("_" ^ lst)) ["abstract"; "assert"; "boolean"; "break"; "byte"; "case"; "catch"; "char"; "class";
-		"const"; "continue"; "default"; "do"; "double"; "else"; "enum"; "extends"; "final";
-		"false"; "finally"; "float"; "for"; "goto"; "if"; "implements"; "import"; "instanceof"; "int";
-		"interface"; "long"; "native"; "new"; "null"; "package"; "private"; "protected"; "public"; "return"; "short";
-		"static"; "strictfp"; "super"; "switch"; "synchronized"; "this"; "throw"; "throws"; "transient"; "true"; "try";
-		"void"; "volatile"; "while"; ];
-	res
-
-let dynamic_anon = mk_anon (ref Closed)
-
-let rec get_class_modifiers meta cl_type cl_access cl_modifiers =
-	match meta with
-		| [] -> cl_type,cl_access,cl_modifiers
-		(*| (Meta.Struct,[],_) :: meta -> get_class_modifiers meta "struct" cl_access cl_modifiers*)
-		| (Meta.Protected,[],_) :: meta -> get_class_modifiers meta cl_type "protected" cl_modifiers
-		| (Meta.Internal,[],_) :: meta -> get_class_modifiers meta cl_type "" cl_modifiers
-		(* no abstract for now | (":abstract",[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("abstract" :: cl_modifiers)
-		| (Meta.Static,[],_) :: meta -> get_class_modifiers meta cl_type cl_access ("static" :: cl_modifiers) TODO: support those types *)
-		| _ :: meta -> get_class_modifiers meta cl_type cl_access cl_modifiers
-
-let rec get_fun_modifiers meta access modifiers =
-	match meta with
-		| [] -> access,modifiers
-		| (Meta.Protected,[],_) :: meta -> get_fun_modifiers meta "protected" modifiers
-		| (Meta.Internal,[],_) :: meta -> get_fun_modifiers meta "" modifiers
-		| (Meta.ReadOnly,[],_) :: meta -> get_fun_modifiers meta access ("final" :: modifiers)
-		(*| (Meta.Unsafe,[],_) :: meta -> get_fun_modifiers meta access ("unsafe" :: modifiers)*)
-		| (Meta.Volatile,[],_) :: meta -> get_fun_modifiers meta access ("volatile" :: modifiers)
-		| (Meta.Transient,[],_) :: meta -> get_fun_modifiers meta access ("transient" :: modifiers)
-		| (Meta.Native,[],_) :: meta -> get_fun_modifiers meta access ("native" :: modifiers)
-		| (Meta.NativeJni,[],_) :: meta -> get_fun_modifiers meta access ("native" :: modifiers)
-		| _ :: meta -> get_fun_modifiers meta access modifiers
-
-let generate con =
-	let exists = ref false in
-	List.iter (fun java_lib ->
-		if String.ends_with java_lib#get_file_path "hxjava-std.jar" then begin
-			exists := true;
-			java_lib#add_flag NativeLibraries.FlagIsStd;
-		end;
-	) con.native_libs.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 | _ -> die "" __LOC__);
-	gen.gclasses.nativearray_len <- (fun e p -> mk_field_access gen e "length" p);
-
-	let fn_cl = get_cl (get_type gen (["haxe";"lang"],"Function")) in
-
-	let runtime_cl = get_cl (get_type gen (["haxe";"lang"],"Runtime")) in
-	let nulltabstract = get_abstract (get_type gen ([],"Null")) in
-
-	(*let string_ref = get_cl ( get_type gen (["haxe";"lang"], "StringRefl")) in*)
-
-	let ti64 = match ( get_type gen (["java"], "Int64") ) with | TAbstractDecl a -> TAbstract(a,[]) | _ -> die "" __LOC__ in
-
-	let has_tdynamic params =
-		List.exists (fun e -> match run_follow gen e with | TDynamic _ -> true | _ -> false) params
-	in
-
-	(*
-		The type parameters always need to be changed to their boxed counterparts
-	*)
-	let change_param_type md params =
-		match md with
-			| TClassDecl( { cl_path = (["java"], "NativeArray") } ) -> params
-			| TAbstractDecl { a_path=[],("Class" | "Enum") } | TClassDecl { cl_path = (["java";"lang"],("Class"|"Enum")) } ->
-				List.map (fun _ -> t_dynamic) params
-			| _ ->
-				match params with
-					| [] -> []
-					| _ ->
-						if has_tdynamic params then List.map (fun _ -> t_dynamic) params else
-							List.map (fun t ->
-								let f_t = gen.gfollow#run_f t in
-								match f_t  with
-									| TAbstract ({ a_path = ([], "Bool") },[])
-									| TAbstract ({ a_path = ([],"Float") },[])
-									| TInst ({ cl_path = ["haxe"],"Int32" },[])
-									| TInst ({ cl_path = ["haxe"],"Int64" },[])
-									| TAbstract ({ a_path = ([],"Int") },[])
-									| TType ({ t_path = ["java"], "Int64" },[])
-									| TAbstract ({ a_path = ["java"], "Int64" },[])
-									| TType ({ t_path = ["java"],"Int8" },[])
-									| TAbstract ({ a_path = ["java"],"Int8" },[])
-									| TType ({ t_path = ["java"],"Int16" },[])
-									| TAbstract ({ a_path = ["java"],"Int16" },[])
-									| TType ({ t_path = ["java"],"Char16" },[])
-									| TAbstract ({ a_path = ["java"],"Char16" },[])
-									| TType ({ t_path = [],"Single" },[])
-									| TAbstract ({ a_path = [],"Single" },[]) ->
-										TAbstract(nulltabstract, [f_t])
-									(*| TAbstract ({ a_path = [], "Null"*)
-									| TInst (cl, ((_ :: _) as p)) when cl.cl_path <> (["java"],"NativeArray") ->
-										(* TInst(cl, List.map (fun _ -> t_dynamic) p) *)
-										TInst(cl,p)
-									| TEnum (e, ((_ :: _) as p)) ->
-										TEnum(e, List.map (fun _ -> t_dynamic) p)
-									| _ -> t
-							) params
-	in
-
-	let change_clname name =
-		String.map (function | '$' -> '.' | c -> c) name
-	in
-	let change_id name = try Hashtbl.find reserved name with | Not_found -> name in
-	let rec change_ns ns = match ns with
-		| [] -> ["haxe"; "root"]
-		| _ -> List.map change_id 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
-
-	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") },[])
-			| TInst( { cl_path = (["haxe"], "Int32") }, [] )
-			| TInst( { cl_path = (["haxe"], "Int64") }, [] )
-			| TType ({ t_path = ["java"], "Int64" },[])
-			| TAbstract ({ a_path = ["java"], "Int64" },[])
-			| TType ({ t_path = ["java"],"Int8" },[])
-			| TAbstract ({ a_path = ["java"],"Int8" },[])
-			| TType ({ t_path = ["java"],"Int16" },[])
-			| TAbstract ({ a_path = ["java"],"Int16" },[])
-			| TType ({ t_path = ["java"],"Char16" },[])
-			| TAbstract ({ a_path = ["java"],"Char16" },[])
-			| TType ({ t_path = [],"Single" },[])
-			| TAbstract ({ a_path = [],"Single" },[]) ->
-					Some t
-			| TAbstract (({ a_path = [],"Null" } as tab),[t2]) ->
-					Some (TAbstract(tab,[gen.gfollow#run_f t2]))
-			| TType ({ t_path = ["haxe";"_Rest"],"NativeRest" } as td, [t2]) ->
-					Some (gen.gfollow#run_f (follow (TType (td,[get_boxed gen t2]))))
-			| TAbstract ({ a_path = ["haxe"],"Rest" } as a, [t2]) ->
-					Some (gen.gfollow#run_f ( Abstract.get_underlying_type a [get_boxed gen t2]) )
-			| 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 change_path path = (change_ns (fst path), change_clname (snd path)) in
-
-	let path_s path meta = try
-		match Meta.get Meta.JavaCanonical meta with
-			| (Meta.JavaCanonical, [EConst(String(pack,_)), _; EConst(String(name,_)), _], _) ->
-				if pack = "" then
-					name
-				else
-					pack ^ "." ^ name
-			| _ -> raise Not_found
-		with Not_found -> match path with
-			| (ns,clname) -> s_type_path (change_ns ns, change_clname clname)
-	in
-
-	let cl_cl = get_cl (get_type gen (["java";"lang"],"Class")) in
-
-	let cl_boolean = get_cl (get_type gen (["java";"lang"],"Boolean")) in
-	let cl_double = get_cl (get_type gen (["java";"lang"],"Double")) in
-	let cl_integer = get_cl (get_type gen (["java";"lang"],"Integer")) in
-	let cl_byte = get_cl (get_type gen (["java";"lang"],"Byte")) in
-	let cl_short = get_cl (get_type gen (["java";"lang"],"Short")) in
-	let cl_character = get_cl (get_type gen (["java";"lang"],"Character")) in
-	let cl_float = get_cl (get_type gen (["java";"lang"],"Float")) in
-	let cl_long = get_cl (get_type gen (["java";"lang"],"Long")) in
-
-	let rec real_type t =
-		let t = gen.gfollow#run_f t in
-		match t with
-			| TAbstract({ a_path = ([], "Null") }, [t]) when is_java_basic_type (gen.gfollow#run_f t) -> t_dynamic
-			| TAbstract({ a_path = ([], "Null") }, [t]) -> (
-				match gen.gfollow#run_f t with
-				| TAbstract( { a_path = ([], "Bool") }, [] ) ->
-					TInst(cl_boolean, [])
-				| TAbstract( { a_path = ([], "Float") }, [] ) ->
-					TInst(cl_double, [])
-				| TAbstract( { a_path = ([], "Int") }, [] ) ->
-					TInst(cl_integer, [])
-				| TAbstract( { a_path = (["java"], "Int8") }, [] ) ->
-					TInst(cl_byte, [])
-				| TAbstract( { a_path = (["java"], "Int16") }, [] ) ->
-					TInst(cl_short, [])
-				| TAbstract( { a_path = (["java"], "Char16") }, [] ) ->
-					TInst(cl_character, [])
-				| TAbstract( { a_path = ([], "Single") }, [] ) ->
-					TInst(cl_float, [])
-				| TAbstract( { a_path = (["java"], "Int64") }, [] )
-				| TAbstract( { a_path = (["haxe"], "Int64") }, [] ) ->
-					TInst(cl_long, [])
-				| _ ->
-					real_type t
-			)
-			| TAbstract (a, pl) when not (Meta.has Meta.CoreType a.a_meta) ->
-				real_type (Abstract.get_underlying_type a pl)
-			| TInst( { cl_path = (["haxe"], "Int32") }, [] ) -> gen.gcon.basic.tint
-			| TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> ti64
-			| TAbstract( { a_path = ([], "Class") }, p	)
-			| TAbstract( { a_path = ([], "Enum") }, p  )
-			| TInst( { cl_path = ([], "Class") }, p  )
-			| TInst( { cl_path = ([], "Enum") }, p	) -> TInst(cl_cl,[t_dynamic])
-			| TEnum(e,params) -> TEnum(e, List.map (fun _ -> t_dynamic) params)
-			| TInst(c,params) when Meta.has Meta.Enum c.cl_meta ->
-				TInst(c, List.map (fun _ -> t_dynamic) params)
-			| TInst({ cl_kind = KExpr _ }, _) -> t_dynamic
-			| TInst _ -> t
-			| TType _ | TAbstract _ -> t
-			| TAnon (anon) -> (match !(anon.a_status) with
-				| Statics _ | EnumStatics _ | AbstractStatics _ -> t
-				| _ -> t_dynamic)
-			| TFun _ -> TInst(fn_cl,[])
-			| _ -> t_dynamic
-	in
-
-	let scope = ref PMap.empty in
-	let imports = ref [] in
-
-	let clear_scope () =
-		scope := PMap.empty;
-		imports := [];
-	in
-
-	let add_scope name =
-		scope := PMap.add name () !scope
-	in
-
-	let add_import pos path meta =
-		let name = snd path in
-		let rec loop = function
-			| (pack, n) :: _ when name = n ->
-					if path <> (pack,n) then
-						gen.gcon.error ("This expression cannot be generated because " ^ path_s path meta ^ " is shadowed by the current scope and ") pos
-			| _ :: tl ->
-					loop tl
-			| [] ->
-					(* add import *)
-					imports := path :: !imports
-		in
-		loop !imports
-	in
-
-	let path_s_import pos path meta = match path with
-		| [], name when PMap.mem name !scope ->
-				gen.gcon.error ("This expression cannot be generated because " ^ name ^ " is shadowed by the current scope") pos;
-				name
-		| pack1 :: _, name when PMap.mem pack1 !scope -> (* exists in scope *)
-				add_import pos path meta;
-				(* check if name exists in scope *)
-				if PMap.mem name !scope then
-					gen.gcon.error ("This expression cannot be generated because " ^ pack1 ^ " and " ^ name ^ " are both shadowed by the current scope") pos;
-				name
-		| _ -> path_s path meta
-	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 _ | AbstractStatics _ -> false
-				| _ -> true
-			)
-		| _ -> false
-	in
-
-	let rec t_s stack pos t =
-		if List.exists (fast_eq t) stack then
-			path_s_import pos (["java";"lang"], "Object") []
-		else begin
-			let stack = t :: stack in
-			match real_type t with
-				(* basic types *)
-				| TAbstract ({ a_path = ([], "Bool") },[]) -> "boolean"
-				| TAbstract ({ a_path = ([], "Void") },[]) ->
-						path_s_import pos (["java";"lang"], "Object") []
-				| TAbstract ({ a_path = ([],"Float") },[]) -> "double"
-				| TAbstract ({ a_path = ([],"Int") },[]) -> "int"
-				| TType ({ t_path = ["java"], "Int64" },[])
-				| TAbstract ({ a_path = ["java"], "Int64" },[]) -> "long"
-				| TType ({ t_path = ["java"],"Int8" },[])
-				| TAbstract ({ a_path = ["java"],"Int8" },[]) -> "byte"
-				| TType ({ t_path = ["java"],"Int16" },[])
-				| TAbstract ({ a_path = ["java"],"Int16" },[]) -> "short"
-				| TType ({ t_path = ["java"],"Char16" },[])
-				| TAbstract ({ a_path = ["java"],"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 = (["java"], "NativeArray") }, [param]) ->
-					let rec check_t_s t =
-						match real_type t with
-							| TInst({ cl_path = (["java"], "NativeArray") }, [param]) ->
-								(check_t_s param) ^ "[]"
-							| _ -> t_s stack pos (run_follow gen t)
-					in
-					(check_t_s param) ^ "[]"
-
-				(* end of basic types *)
-				| TInst ({ cl_kind = KTypeParameter _; cl_path=p }, []) -> snd p
-				| TAbstract ({ a_path = [], "Dynamic" },[]) ->
-						path_s_import pos (["java";"lang"], "Object") []
-				| TMono r -> (match r.tm_type with | None -> "java.lang.Object" | Some t -> t_s stack pos (run_follow gen t))
-				| TInst ({ cl_path = [], "String" }, []) ->
-						path_s_import pos (["java";"lang"], "String") []
-				| TAbstract ({ a_path = [], "Class" }, [p]) | TAbstract ({ a_path = [], "Enum" }, [p])
-				| TInst ({ cl_path = [], "Class" }, [p]) | TInst ({ cl_path = [], "Enum" }, [p]) ->
-						path_param_s stack pos (TClassDecl cl_cl) (["java";"lang"], "Class") [p] []
-				| TAbstract ({ a_path = [], "Class" }, _) | TAbstract ({ a_path = [], "Enum" }, _)
-				| TInst ({ cl_path = [], "Class" }, _) | TInst ({ cl_path = [], "Enum" }, _) ->
-						path_s_import pos (["java";"lang"], "Class") []
-				| TEnum ({e_path = p; e_meta = meta}, _) ->
-						path_s_import pos p meta
-				| TInst (({cl_path = p; cl_meta = meta} as cl), _) when Meta.has Meta.Enum cl.cl_meta ->
-						path_s_import pos p meta
-				| TInst (({cl_path = p; cl_meta = meta} as cl), params) -> (path_param_s stack pos (TClassDecl cl) p params meta)
-				| TType (({t_path = p; t_meta = meta} as t), params) -> (path_param_s stack pos (TTypeDecl t) p params meta)
-				| TAnon (anon) ->
-					(match !(anon.a_status) with
-						| Statics _ | EnumStatics _ | AbstractStatics _ ->
-								path_s_import pos (["java";"lang"], "Class") []
-						| _ ->
-								path_s_import pos (["java";"lang"], "Object") [])
-					| TDynamic _ ->
-							path_s_import pos (["java";"lang"], "Object") []
-				(* 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) ^ " ]"); die "" __LOC__ end else "[ !TypeError " ^ (Type.s_type (Type.print_context()) t) ^ " ]"
-		end
-	and param_t_s stack pos t =
-		match run_follow gen t with
-			| TAbstract ({ a_path = ([], "Bool") },[]) ->
-					path_s_import pos (["java";"lang"], "Boolean") []
-			| TAbstract ({ a_path = ([],"Float") },[]) ->
-					path_s_import pos (["java";"lang"], "Double") []
-			| TAbstract ({ a_path = ([],"Int") },[]) ->
-					path_s_import pos (["java";"lang"], "Integer") []
-			| TType ({ t_path = ["java"], "Int64" },[])
-			| TAbstract ({ a_path = ["java"], "Int64" },[]) ->
-					path_s_import pos (["java";"lang"], "Long") []
-			| TInst ({ cl_path = ["haxe"],"Int64" },[])
-			| TAbstract ({ a_path = ["haxe"],"Int64" },[]) ->
-					path_s_import pos (["java";"lang"], "Long") []
-			| TInst ({ cl_path = ["haxe"],"Int32" },[])
-			| TAbstract ({ a_path = ["haxe"],"Int32" },[]) ->
-					path_s_import pos (["java";"lang"], "Integer") []
-			| TType ({ t_path = ["java"],"Int8" },[])
-			| TAbstract ({ a_path = ["java"],"Int8" },[]) ->
-					path_s_import pos (["java";"lang"], "Byte") []
-			| TType ({ t_path = ["java"],"Int16" },[])
-			| TAbstract ({ a_path = ["java"],"Int16" },[]) ->
-					path_s_import pos (["java";"lang"], "Short") []
-			| TType ({ t_path = ["java"],"Char16" },[])
-			| TAbstract ({ a_path = ["java"],"Char16" },[]) ->
-					path_s_import pos (["java";"lang"], "Character") []
-			| TType ({ t_path = [],"Single" },[])
-			| TAbstract ({ a_path = [],"Single" },[]) ->
-					path_s_import pos (["java";"lang"], "Float") []
-			| TDynamic _ -> "?"
-			| TInst (cl, params) -> t_s stack pos (TInst(cl, change_param_type (TClassDecl cl) params))
-			| TType (cl, params) -> t_s stack pos (TType(cl, change_param_type (TTypeDecl cl) params))
-			| TEnum (e, params) -> t_s stack pos (TEnum(e, change_param_type (TEnumDecl e) params))
-			| _ -> t_s stack pos t
-
-	and path_param_s stack pos md path params meta =
-			match params with
-				| [] -> path_s_import pos path meta
-				| _ when has_tdynamic (change_param_type md params) -> path_s_import pos path meta
-				| _ -> sprintf "%s<%s>" (path_s_import pos path meta) (String.concat ", " (List.map (fun t -> param_t_s stack pos t) (change_param_type md params)))
-	in
-
-	let t_s = t_s []
-	and param_t_s = param_t_s []
-	and path_param_s = path_param_s [] in
-
-	let rett_s pos t =
-		match t with
-			| TAbstract ({ a_path = ([], "Void") },[]) -> "void"
-			| _ -> t_s pos t
-	in
-
-	let high_surrogate c = (c lsr 10) + 0xD7C0 in
-	let low_surrogate c = (c land 0x3FF) lor 0xDC00 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%.4x\\u%.4x" (high_surrogate c) (low_surrogate 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 (UCharExt.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
-			| TIdent "__fallback__"
-			| TCall ({ eexpr = TIdent "__lock__" }, _ ) -> false
-			| 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 pos md =
-		let md = follow_module (gen.gfollow#run_f) md in
-		match md with
-			| TClassDecl (cl) ->
-				t_s pos (TInst(cl,[]))
-			| TEnumDecl (e) ->
-				t_s pos (TEnum(e,[]))
-			| TTypeDecl t ->
-				t_s pos (TType(t, []))
-			| TAbstractDecl a ->
-				t_s pos (TAbstract(a, []))
-	in
-
-	(*
-		it seems that Java doesn't like when you create a new array with the type parameter defined
-		so we'll just ignore all type parameters, and hope for the best!
-	*)
-	let rec transform_nativearray_t t = match real_type t with
-		| TInst( ({ cl_path = (["java"], "NativeArray") } as narr), [t]) ->
-			TInst(narr, [transform_nativearray_t t])
-		| TInst(cl, params) -> TInst(cl, List.map (fun _ -> t_dynamic) params)
-		| TEnum(e, params) -> TEnum(e, List.map (fun _ -> t_dynamic) params)
-		| TType(t, params) -> TType(t, List.map (fun _ -> t_dynamic) params)
-		| _ -> t
-	in
-
-	let rec extract_tparams params el =
-		match el with
-			| ({ eexpr = TIdent "$type_param" } as tp) :: tl ->
-				extract_tparams (tp.etype :: params) tl
-			| _ -> (params, el)
-	in
-
-	let line_directive =
-		if Common.defined gen.gcon Define.RealPosition then
-			fun w p -> ()
-		else fun w p ->
-			let cur_line = Lexer.get_error_line p in
-			let file = Path.get_full_path p.pfile in
-			print w "//line %d \"%s\"" cur_line (StringHelper.s_escape file); newline w
-	in
-
-	let extract_statements expr =
-		let ret = ref [] in
-		let rec loop expr = match expr.eexpr with
-			| TCall ({ eexpr = TIdent ("__is__" | "__typeof__" | "__array__")}, el) ->
-				List.iter loop el
-			| TNew ({ cl_path = (["java"], "NativeArray") }, params, [ size ]) ->
-				()
-			| TUnop (Ast.Increment, _, _)
-			| TUnop (Ast.Decrement, _, _)
-			| TBinop (Ast.OpAssign, _, _)
-			| TBinop (Ast.OpAssignOp _, _, _)
-			| TIdent "__fallback__"
-			| TIdent "__sbreak__" ->
-				ret := expr :: !ret
-			| TConst _
-			| TLocal _
-			| TIdent _
-			| TArray _
-			| TBinop _
-			| TField _
-			| TEnumParameter _
-			| TTypeExpr _
-			| TObjectDecl _
-			| TArrayDecl _
-			| TCast _
-			| 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
-
-	let expr_s w e =
-		in_value := false;
-		let rec expr_s w e =
-			let was_in_value = !in_value in
-			in_value := true;
-			match e.eexpr with
-				| TConst c ->
-					(match c with
-						| TInt i32 ->
-							print w "%ld" i32;
-						| TFloat s ->
-							write w s;
-							(* fix for Int notation, which only fit in a Float *)
-							(if not (String.contains s '.' || String.contains s 'e' || String.contains s 'E') then write w ".0");
-						| TString s -> print w "\"%s\"" (escape s)
-						| TBool b -> write w (if b then "true" else "false")
-						| TNull ->
-							(match real_type e.etype with
-								| TAbstract( { a_path = (["java"], "Int64") }, [] )
-								| TInst( { cl_path = (["haxe"], "Int64") }, [] ) -> write w "0L"
-								| TInst( { cl_path = (["haxe"], "Int32") }, [] )
-								| TAbstract ({ a_path = ([], "Int") },[]) -> expr_s w ({ e with eexpr = TConst(TInt Int32.zero) })
-								| TAbstract ({ a_path = ([], "Float") },[]) -> expr_s w ({ e with eexpr = TConst(TFloat "0.0") })
-								| TAbstract ({ a_path = ([], "Bool") },[]) -> write w "false"
-								| TAbstract _ when like_int e.etype ->
-									expr_s w (mk_cast e.etype { e with eexpr = TConst(TInt Int32.zero) })
-								| TAbstract _ when like_float e.etype ->
-									expr_s w (mk_cast e.etype { e with eexpr = TConst(TFloat "0.0") } )
-								| t -> write w ("null") )
-						| TThis -> write w "this"
-						| TSuper -> write w "super")
-				| TIdent "__fallback__" -> ()
-				| TIdent "__sbreak__" -> write w "break"
-				| TIdent "__undefined__" ->
-					write w (t_s e.epos (TInst(runtime_cl, List.map (fun _ -> t_dynamic) runtime_cl.cl_params)));
-					write w ".undefined";
-				| TLocal var ->
-					write_id w var.v_name
-				| TIdent s ->
-					write_id w s
-				| TField(_, FEnum(en,ef)) ->
-					let s = ef.ef_name in
-					print w "%s." (path_s_import e.epos en.e_path en.e_meta); 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 (e, FStatic(_, 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
-				| TField (e, s) ->
-					expr_s w e; write w "."; write_field w (field_name s)
-				| TTypeExpr (TClassDecl { cl_path = (["haxe"], "Int32") }) ->
-					write w (path_s_import e.epos (["haxe"], "Int32") [])
-				| TTypeExpr (TClassDecl { cl_path = (["haxe"], "Int64") }) ->
-					write w (path_s_import e.epos (["haxe"], "Int64") [])
-				| TTypeExpr mt -> write w (md_s e.epos mt)
-				| TParenthesis e ->
-					write w "("; expr_s w e; write w ")"
-				| TMeta ((Meta.LoopLabel,[(EConst(Int (n, _)),_)],_), e) ->
-					(match e.eexpr with
-					| TFor _ | TWhile _ ->
-						print w "label%s:" n;
-						newline w;
-						expr_s w e;
-					| TBreak -> print w "break label%s" n
-					| _ -> die "" __LOC__)
-				| TMeta (_,e) ->
-					expr_s w e
-				| TCall ({ eexpr = TField(_, FStatic({ cl_path = (["haxe";"_Rest"],"Rest_Impl_") }, { cf_name = "createNative" })) }, el) ->
-					(match follow e.etype with
-					| TInst (cls, params) ->
-						expr_s w { e with eexpr = TNew(cls,params,el) }
-					| _ -> die ~p:e.epos "Unexpected return type of haxe.Rest.createNative" __LOC__)
-				| TCall ({ eexpr = TIdent "__array__" }, el)
-				| TCall ({ eexpr = TField(_, FStatic({ cl_path = (["java"],"NativeArray") }, { cf_name = "make" })) }, el)
-				| TArrayDecl el when t_has_type_param e.etype ->
-					let _, el = extract_tparams [] el in
-					print w "( (%s) (new %s " (t_s e.epos e.etype) (t_s e.epos (replace_type_param 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 = TIdent "__array__" }, el)
-				| TCall ({ eexpr = TField(_, FStatic({ cl_path = (["java"],"NativeArray") }, { cf_name = "make" })) }, el)
-				| TArrayDecl el ->
-					let _, el = extract_tparams [] el in
-					print w "new %s" (param_t_s e.epos (transform_nativearray_t e.etype));
-					let is_double = match follow e.etype with
-					 | TInst(_,[ t ]) -> if like_float t && not (like_int t) then Some t else None
-					 | _ -> None
-					in
-
-					write w "{";
-					ignore (List.fold_left (fun acc e ->
-						(if acc <> 0 then write w ", ");
-						(* this is a hack so we are able to convert ints to boxed Double / Float when needed *)
-						let e = if is_some is_double then mk_cast (get is_double) e else e in
-
-						expr_s w e;
-						acc + 1
-					) 0 el);
-					write w "}"
-				| TCall( ( { eexpr = TField(_, FStatic({ cl_path = ([], "String") }, { cf_name = "fromCharCode" })) } ), [cc] ) ->
-						write w "new java.lang.String( java.lang.Character.toChars((int) ";
-						expr_s w cc;
-						write w ") )"
-				| TCall ({ eexpr = TIdent "__is__" }, [ expr; { eexpr = TTypeExpr(md) } ] ) ->
-					write w "( ";
-					expr_s w expr;
-					write w " instanceof ";
-					write w (md_s e.epos md);
-					write w " )"
-				| TCall ({ eexpr = TIdent "__java__" }, [ { eexpr = TConst(TString(s)) } ] ) ->
-					write w s
-				| TCall ({ eexpr = TIdent "__java__" }, { eexpr = TConst(TString(s)) } :: tl ) ->
-					Codegen.interpolate_code gen.gcon s tl (write w) (expr_s w) e.epos
-				| TCall ({ eexpr = TIdent "__lock__" }, [ eobj; eblock ] ) ->
-					write w "synchronized(";
-					let rec loop eobj = match eobj.eexpr with
-						| TTypeExpr md ->
-							expr_s w eobj;
-							write w ".class"
-						| TMeta(_,e) | TParenthesis(e) ->
-							loop e
-						| _ ->
-							expr_s w eobj
-					in
-					loop eobj;
-					write w ")";
-					(match eblock.eexpr with
-					| TBlock(_ :: _) ->
-						expr_s w eblock
-					| _ ->
-						begin_block w;
-						expr_s w eblock;
-						if has_semicolon eblock then write w ";";
-						end_block w;
-					)
-				| TCall ({ eexpr = TIdent "__typeof__" }, [ { eexpr = TTypeExpr md } as expr ] ) ->
-					expr_s w expr;
-					write w ".class"
-				| TCall (e, el) ->
-					let params, el = extract_tparams [] el in
-
-					expr_s w e;
-
-					(*(match params with
-						| [] -> ()
-						| params ->
-							let md = match e.eexpr with
-								| TField(ef, _) -> t_to_md (run_follow gen ef.etype)
-								| _ -> die "" __LOC__
-							in
-							write w "<";
-							ignore (List.fold_left (fun acc t ->
-								(if acc <> 0 then write w ", ");
-								write w (param_t_s (change_param_type md t));
-								acc + 1
-							) 0 params);
-							write w ">"
-					);*)
-
-					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_path = (["java"], "NativeArray") } as cl), params, [ size ]) ->
-					let rec check_t_s t times =
-						match real_type t with
-							| TInst({ cl_path = (["java"], "NativeArray") }, [param]) ->
-								(check_t_s param (times+1))
-							| _ ->
-								print w "new %s[" (t_s e.epos (transform_nativearray_t 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 e.epos (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 "null /* This code should never be reached. It was produced by the use of @:generic on a new type parameter instance: %s */" (path_param_s e.epos (TClassDecl cl) cl.cl_path params cl.cl_meta)
-				| TNew (cl, params, el) ->
-					write w "new ";
-					write w (path_param_s e.epos (TClassDecl cl) cl.cl_path params cl.cl_meta);
-					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.Spread, Prefix, e) -> expr_s w e
-				| 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 e.epos 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 ->
-						List.iter (fun e ->
-							in_value := false;
-							line_directive w e.epos;
-							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 ->
-					write w "( ";
-					expr_s w (mk_paren econd);
-					write w " ? ";
-					expr_s w (mk_paren e1);
-					write w " : ";
-					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;
-							expr_s w (mk_block 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);
-					begin_block w;
-					List.iter (fun (el, e) ->
-						List.iter (fun e ->
-							write w "case ";
-							in_value := true;
-							(match e.eexpr with
-								| TField(_, FEnum(e, ef)) ->
-									let changed_name = change_id ef.ef_name in
-									write w changed_name
-								| _ ->
-									expr_s w e);
-							write w ":";
-							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);
-					let pos = e.epos in
-					List.iter (fun (var, e) ->
-						print w "catch (%s %s)" (t_s pos 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 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.epos 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 die "" __LOC__
-				| TObjectDecl _ -> write w "[ obj decl not supported ]"; if !strict_mode then die "" __LOC__
-				| TFunction _ -> write w "[ func decl not supported ]"; if !strict_mode then die "" __LOC__
-				| TEnumParameter _ -> write w "[ enum parameter not supported ]"; if !strict_mode then die "" __LOC__
-				| TEnumIndex _ -> write w "[ enum index not supported ]"; if !strict_mode then die "" __LOC__
-		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 "{";
-			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 gen_annotations w ?(add_newline=true) metadata =
-		List.iter (function
-			| Meta.Meta, [meta], _ ->
-				write w "@";
-				gen_spart w meta;
-				if add_newline then newline w else write w " ";
-			| _ -> ()
-		) metadata
-	in
-
-	let argt_s p t =
-		let w = new_source_writer () in
-		let rec run t =
-			match t with
-				| TType (tdef,p) ->
-					gen_annotations w ~add_newline:false tdef.t_meta;
-					run (follow_once t)
-				| TMono r ->
-					(match r.tm_type with
-					| Some t -> run t
-					| _ -> () (* avoid infinite loop / should be the same in this context *))
-				| TLazy f ->
-					run (lazy_type f)
-				| _ -> ()
-		in
-		run t;
-		let ret = t_s p t in
-		let c = contents w in
-		if c <> "" then
-			c ^ " " ^ ret
-		else
-			ret
-	in
-
-	let get_string_params cl_params =
-		match cl_params with
-			| [] ->
-				("","")
-			| _ ->
-				let params = sprintf "<%s>" (String.concat ", " (List.map (fun tp -> match follow tp.ttp_type with | TInst(cl, _) -> snd cl.cl_path | _ -> die "" __LOC__) cl_params)) in
-				let params_extends = List.fold_left (fun acc {ttp_name=name;ttp_type=t} ->
-					match run_follow gen t with
-						| TInst (cl, p) ->
-							(match cl.cl_implements with
-								| [] -> acc
-								| _ -> acc) (* TODO
-								| _ -> (sprintf " where %s : %s" name (String.concat ", " (List.map (fun (cl,p) -> path_param_s (TClassDecl cl) cl.cl_path p) cl.cl_implements))) :: acc ) *)
-						| _ -> trace (t_s null_pos t); die "" __LOC__ (* FIXME it seems that a cl_params will never be anything other than cl.cl_params. I'll take the risk and fail if not, just to see if that confirms *)
-				) [] cl_params in
-				(params, String.concat " " params_extends)
-	in
-
-	let write_parts w parts =
-		let parts = List.filter (fun s -> s <> "") parts in
-		write w (String.concat " " parts)
-	in
-
-	let rec gen_class_field w ?(is_overload=false) is_static cl is_final cf =
-		let is_interface = (has_class_flag cl CInterface) 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
-				(path_s path cl.cl_meta) ^ "." ^ fn_name, false, true
-			| name -> name, false, false
-		in
-		(match cf.cf_kind with
-			| Var _
-			| Method (MethDynamic) when Type.is_physical_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
-					write_parts w (access :: (if is_static then "static" else "") :: modifiers @ [(t_s cf.cf_pos (run_follow gen cf.cf_type)); (change_field name)]);
-					(match cf.cf_expr with
-						| Some e ->
-								write w " = ";
-								expr_s w e;
-								write w ";"
-						| None -> write w ";"
-					)
-				end (* TODO see how (get,set) variable handle when they are interfaces *)
-			| Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
-				List.iter (fun cf -> if (has_class_flag cl CInterface) || cf.cf_expr <> None then
-					gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
-				) cf.cf_overloads
-			| Var _ | Method MethDynamic -> ()
-			| Method mkind ->
-				List.iter (fun cf ->
-					if (has_class_flag cl CInterface) || (has_class_flag cl CAbstract) || cf.cf_expr <> None then
-						gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
-				) cf.cf_overloads;
-				let is_virtual = is_new || (not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false) in
-				let is_override = match cf.cf_name with
-					| "equals" when not is_static ->
-						(match cf.cf_type with
-							| TFun([_,_,t], ret) ->
-								(match (real_type t, real_type ret) with
-									| TDynamic _, TAbstract ({ a_path = ([], "Bool") },[])
-									| TAnon _, TAbstract ({ a_path = ([], "Bool") },[]) -> true
-									| _ -> has_class_field_flag cf CfOverride
-								)
-							| _ -> has_class_field_flag cf CfOverride)
-					| "toString" when not is_static ->
-						(match cf.cf_type with
-							| TFun([], ret) ->
-								(match real_type ret with
-									| TInst( { cl_path = ([], "String") }, []) -> true
-									| _ -> gen.gcon.error "A toString() function should return a String!" cf.cf_pos; false
-								)
-							| _ -> has_class_field_flag cf CfOverride
-						)
-					| "hashCode" when not is_static ->
-						(match cf.cf_type with
-							| TFun([], ret) ->
-								(match real_type ret with
-									| TAbstract ({ a_path = ([], "Int") },[]) ->
-										true
-									| _ -> gen.gcon.error "A hashCode() function should return an Int!" cf.cf_pos; false
-								)
-							| _ -> has_class_field_flag cf CfOverride
-						)
-					| _ -> has_class_field_flag cf CfOverride
-				in
-				let visibility = if is_interface then "" else "public" in
-
-				let visibility, modifiers = get_fun_modifiers cf.cf_meta visibility [] in
-				let is_abstract = has_class_field_flag cf CfAbstract in
-				let modifiers = if is_abstract then "abstract" :: modifiers else modifiers in
-				let visibility, is_virtual = if is_explicit_iface then "",false else visibility, is_virtual in
-				let v_n = if is_static then "static" else if is_override && not is_interface then "" else if not is_virtual then "final" else "" in
-				let cf_type = if is_override && not is_overload && not (has_class_field_flag cf CfOverload) then match field_access gen (TInst(cl, extract_param_types cl.cl_params)) cf.cf_name with | FClassField(_,_,_,_,_,actual_t,_) -> actual_t | _ -> die "" __LOC__ else cf.cf_type in
-
-				let params = extract_param_types cl.cl_params in
-				let ret_type, args, has_rest_args = match follow cf_type, follow cf.cf_type with
-					| TFun (strbtl, t), TFun(rargs, _) ->
-						let ret_type = apply_params cl.cl_params params (real_type t)
-						and args =
-							List.map2 (fun(_,_,t) (n,o,_) ->
-								(n,o,apply_params cl.cl_params params (real_type t))
-							) strbtl rargs
-						and rest =
-							match List.rev rargs with
-							| (_,_,t) :: _ -> ExtType.is_rest (follow t)
-							| _ -> false
-						in
-						ret_type,args,rest
-					| _ -> die "" __LOC__
-				in
-
-				(if is_override && not is_interface then write w "@Override ");
-				gen_annotations w cf.cf_meta;
-				(* public static void funcName *)
-				let params, _ = get_string_params cf.cf_params in
-
-				write_parts w (visibility :: v_n :: modifiers @ [params; (if is_new then "" else rett_s cf.cf_pos (run_follow gen ret_type)); (change_field name)]);
-
-				(* <T>(string arg1, object arg2) with T : object *)
-				let arg_names =
-					match cf.cf_expr with
-					| Some { eexpr = TFunction tf } ->
-						List.map (fun (var,_) -> change_id var.v_name) tf.tf_args
-					| _ ->
-						List.map (fun (name,_,_) -> change_id name) args
-				in
-				let rec loop acc names args =
-					match names, args with
-					| [], [] -> acc
-					| _, [] | [], _ ->
-						die "" __LOC__
-					| [name], [_,_,TInst ({ cl_path = ["java"],"NativeArray" }, [t])] when has_rest_args ->
-						let arg = sprintf "%s ...%s" (argt_s cf.cf_pos (run_follow gen t)) name in
-						arg :: acc
-					| name :: names, (_,_,t) :: args ->
-						let arg = sprintf "%s %s" (argt_s cf.cf_pos (run_follow gen t)) name in
-						loop (arg :: acc) names args
-				in
-				print w "(%s)" (String.concat ", " (List.rev (loop [] arg_names args)));
-				if is_interface || List.mem "native" modifiers || is_abstract then
-					write w ";"
-				else begin
-					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)
-											| _ -> die "" __LOC__ (* 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
-									in*)
-									expr_s w expr
-								end else begin
-									expr_s w expr;
-								end)
-							| (Meta.Throws, [Ast.EConst (Ast.String(t,_)), _], _) :: tl ->
-								print w " throws %s" t;
-								loop tl
-							| (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
-
-	let gen_class_field w ?(is_overload=false) is_static cl is_final cf =
-		(* This should probably be handled somewhere earlier in the unholy gencommon machinery, but whatever *)
-		if not (has_class_field_flag cf CfExtern) then gen_class_field w ~is_overload is_static cl is_final cf
-	in
-
-	let gen_class w cl =
-		let cf_filters = [ handle_throws ] in
-		List.iter (fun f -> List.iter (f gen) cl.cl_ordered_fields) cf_filters;
-		List.iter (fun f -> List.iter (f gen) cl.cl_ordered_statics) cf_filters;
-		let should_close = match change_ns (fst cl.cl_path) with
-			| [] -> false
-			| ns ->
-				print w "package %s;" (String.concat "." (change_ns ns));
-				newline w;
-				newline w;
-				false
-		in
-
-		let rec loop_meta meta acc =
-			match meta with
-				| (Meta.SuppressWarnings, [Ast.EConst (Ast.String(w,_)),_],_) :: meta -> loop_meta meta (w :: acc)
-				| _ :: meta -> loop_meta meta acc
-				| _ -> acc
-		in
-
-		let suppress_warnings = loop_meta cl.cl_meta [ "rawtypes"; "unchecked" ] in
-
-		write w "import haxe.root.*;";
-		newline w;
-		let w_header = w in
-		let w = new_source_writer () in
-		clear_scope();
-
-		(* add all haxe.root.* to imports *)
-		List.iter (function
-			| TClassDecl { cl_path = ([],c) } ->
-					imports := ([],c) :: !imports
-			| TEnumDecl { e_path = ([],c) } ->
-					imports := ([],c) :: !imports
-			| TAbstractDecl { a_path = ([],c) } ->
-					imports := ([],c) :: !imports
-			| _ -> ()
-		) gen.gtypes_list;
-
-		newline w;
-		write w "@SuppressWarnings(value={";
-		let first = ref true in
-		List.iter (fun s ->
-			(if !first then first := false else write w ", ");
-			print w "\"%s\"" (escape s)
-		) suppress_warnings;
-		write w "})";
-		newline w;
-		gen_annotations w cl.cl_meta;
-
-		let clt, access, modifiers = get_class_modifiers cl.cl_meta (if (has_class_flag cl CInterface) then "interface" else "class") "public" [] in
-		let is_final = has_class_flag cl CFinal in
-		let is_abstract = has_class_flag cl CAbstract in
-		let modifiers = if is_final then "final" :: modifiers else modifiers in
-		let modifiers = if is_abstract then "abstract" :: modifiers else modifiers in
-
-		write_parts w (access :: modifiers @ [clt; (change_clname (snd cl.cl_path))]);
-
-		(* type parameters *)
-		let params, _ = get_string_params cl.cl_params in
-		let cl_p_to_string (c,p) =
-			let p = List.map (fun t -> match follow t with
-				| TMono _ | TDynamic _ -> t_empty
-				| _ -> t) p
-			in
-			path_param_s cl.cl_pos (TClassDecl c) c.cl_path p c.cl_meta
-		in
-		print w "%s" params;
-		(if is_some cl.cl_super then print w " extends %s" (cl_p_to_string (get cl.cl_super)));
-		(match cl.cl_implements with
-			| [] -> ()
-			| _ -> print w " %s %s" (if (has_class_flag cl CInterface) then "extends" else "implements") (String.concat ", " (List.map cl_p_to_string cl.cl_implements))
-		);
-		(* class head ok: *)
-		(* public class Test<A> : X, Y, Z where A : Y *)
-		begin_block w;
-		(* our constructor is expected to be a normal "new" function *
-		if !strict_mode && is_some cl.cl_constructor then die "" __LOC__;*)
-
-		let rec loop cl =
-			List.iter (fun cf -> add_scope cf.cf_name) cl.cl_ordered_fields;
-			List.iter (fun cf -> add_scope cf.cf_name) cl.cl_ordered_statics;
-			match cl.cl_super with
-				| Some(c,_) -> loop c
-				| None -> ()
-		in
-		loop cl;
-
-		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;
-
-		(match gen.gentry_point with
-		| Some (_,cl_main,expr) when cl == cl_main ->
-			write w "public static void main(String[] args)";
-			begin_block w;
-			(try
-				let t = Hashtbl.find gen.gtypes ([], "Sys") in
-				match t with
-				| TClassDecl(cl) when PMap.mem "_args" cl.cl_statics ->
-					write w "Sys._args = args;"; newline w
-				| _ -> ()
-			with Not_found ->
-				());
-			write w "haxe.java.Init.init();";
-			newline w;
-			expr_s w expr;
-			write w ";";
-			end_block w;
-			newline w
-		| _ -> ());
-
-		(match cl.cl_init with
-			| None -> ()
-			| Some init ->
-				write w "static";
-				expr_s w (mk_block init);
-				newline w
-		);
-
-		(if is_some cl.cl_constructor then gen_class_field w false cl is_final (get cl.cl_constructor));
-		(if not (has_class_flag cl CInterface) then List.iter (gen_class_field w true cl is_final) cl.cl_ordered_statics);
-		List.iter (gen_class_field w false cl is_final) cl.cl_ordered_fields;
-
-		end_block w;
-		if should_close then end_block w;
-
-		(* add imports *)
-		List.iter (function
-			| ["haxe";"root"], _ | [], _ -> ()
-			| path ->
-					write w_header "import ";
-					write w_header (path_s path []);
-					write w_header ";\n"
-		) !imports;
-		add_writer w w_header
-	in
-
-
-	let gen_enum w e =
-		let should_close = match change_ns (fst e.e_path) with
-			| [] -> false
-			| ns ->
-				print w "package %s;" (String.concat "." (change_ns ns));
-				newline w;
-				newline w;
-				false
-		in
-
-		gen_annotations 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;
-
-		if should_close then end_block w
-	in
-
-	let module_type_gen w md_tp =
-		Codegen.map_source_header gen.gcon (fun s -> print w "// %s\n" s);
-		match md_tp with
-			| TClassDecl cl ->
-				if not (has_class_flag cl CExtern) then begin
-					gen_class w cl;
-					newline w;
-					newline w
-				end;
-				(not (has_class_flag cl CExtern))
-			| TEnumDecl e ->
-				if not e.e_extern && not (Meta.has Meta.Class e.e_meta) then begin
-					gen_enum w e;
-					newline w;
-					newline w
-				end;
-				(not e.e_extern)
-			| TTypeDecl e ->
-				false
-			| TAbstractDecl a ->
-				false
-	in
-
-	(* generate source code *)
-	init_ctx gen;
-
-	Hashtbl.add gen.gspecial_vars "__is__" true;
-	Hashtbl.add gen.gspecial_vars "__typeof__" true;
-	Hashtbl.add gen.gspecial_vars "__java__" true;
-	Hashtbl.add gen.gspecial_vars "__lock__" true;
-	Hashtbl.add gen.gspecial_vars "__array__" true;
-
-	gen.greal_type <- real_type;
-	gen.greal_type_param <- change_param_type;
-	gen.gspecial_needs_cast <- (fun to_t from_t ->
-		is_boxed_of_t to_t from_t ||
-		is_boxed_of_t from_t to_t ||
-		( (is_boxed_int_type from_t || is_boxed_float_type from_t ) &&
-		  (is_boxed_int_type to_t || is_boxed_float_type to_t || is_int_type to_t || is_float_type to_t) ) ||
-		( (is_boxed_int_type to_t || is_boxed_float_type to_t ) &&
-			(is_boxed_int_type from_t || is_boxed_float_type from_t || is_int_type from_t || is_float_type from_t) )
-	);
-
-	(* 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
-				) 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 get_vmtype t = match real_type t with
-		| TInst({ cl_path = ["java"],"NativeArray" }, tl) -> t
-		| TInst(c,tl) -> TInst(c,List.map (fun _ -> t_dynamic) tl)
-		| TEnum(e,tl) -> TEnum(e, List.map (fun _ -> t_dynamic) tl)
-		| TType(t,tl) -> TType(t, List.map (fun _ -> t_dynamic) tl)
-		| TAbstract(a,tl) -> TAbstract(a, List.map (fun _ -> t_dynamic) tl)
-		| t -> t
-	in
-
-	FixOverrides.configure ~get_vmtype gen;
-
-	let allowed_meta = Hashtbl.create 1 in
-	Hashtbl.add allowed_meta Meta.LoopLabel true;
-	Normalize.configure gen ~allowed_metas:allowed_meta;
-
-	AbstractImplementationFix.configure gen;
-
-	let cl_arg_exc = get_cl (get_type gen (["java";"lang"],"IllegalArgumentException")) in
-	let cl_arg_exc_t = TInst (cl_arg_exc, []) in
-	let mk_arg_exception msg pos = mk (TNew (cl_arg_exc, [], [Texpr.Builder.make_string gen.gcon.basic msg pos])) cl_arg_exc_t pos in
-	let closure_t = ClosuresToClass.DoubleAndDynamicClosureImpl.get_ctx gen (get_cl (get_type gen (["haxe";"lang"],"Function"))) 6 mk_arg_exception in
-	ClosuresToClass.configure gen closure_t;
-
-	let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in
-	let param_enum_base = (get_cl (get_type gen (["haxe";"lang"],"ParamEnum")) ) in
-	let type_enumindex = mk_static_field_access_infer gen.gclasses.cl_type "enumIndex" null_pos [] in
-	let mk_enum_index_call e p =
-		mk (TCall (type_enumindex, [e])) gen.gcon.basic.tint p
-	in
-	EnumToClass.configure gen false true enum_base param_enum_base mk_enum_index_call;
-
-	InterfaceVarsDeleteModf.configure gen;
-
-	let dynamic_object = (get_cl (get_type gen (["haxe";"lang"],"DynamicObject")) ) in
-
-	let object_iface = get_cl (get_type gen (["haxe";"lang"],"IHxObject")) in
-
-	let empty_en = match get_type gen (["haxe";"lang"], "EmptyObject") with TEnumDecl e -> e | _ -> die "" __LOC__ in
-	let empty_ctor_type = TEnum(empty_en, []) in
-	let empty_en_expr = mk (TTypeExpr (TEnumDecl empty_en)) (mk_anon (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_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 get_specialized_postfix t = match t with
-		| TAbstract({a_path = [],"Float"}, _) -> "Float"
-		| TInst({cl_path = [],"String"},_) -> "String"
-		| TAnon _ | TDynamic _ -> "Dynamic"
-		| _ -> print_endline (debug_type t); die "" __LOC__
-	in
-	let rcf_static_insert t = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("insert" ^ get_specialized_postfix t) null_pos [] in
-	let rcf_static_remove t = mk_static_field_access_infer (get_cl (get_type gen (["haxe";"lang"], "FieldLookup"))) ("remove" ^ get_specialized_postfix t) null_pos [] in
-
-	let can_be_float t = like_float (real_type t) in
-
-	let rcf_on_getset_field main_expr field_expr field may_hash may_set is_unsafe =
-		let is_float = can_be_float (if is_none may_set then main_expr.etype else (get may_set).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 is_unsafe = { eexpr = TConst(TBool is_unsafe); etype = basic.tbool; epos = pos } 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 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 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 hash_arg = match may_hash with
-			| None -> []
-			| Some h -> [ { eexpr = TConst(TInt h); etype = basic.tint; epos = field_expr.epos } ]
-		in
-
-		let arr_call = if args <> [] then
-			mk_nativearray_decl gen t_dynamic args ecall.epos
-		else
-			null (gen.gclasses.nativearray t_dynamic) ecall.epos
-		in
-
-
-		let call_args =
-			[field_expr; { field_expr with eexpr = TConst(TString field); etype = basic.tstring } ]
-				@ hash_arg
-				@ [ arr_call ]
-		in
-
-		mk_cast ecall.etype { ecall with eexpr = TCall(infer, call_args); etype = t_dynamic }
-	in
-
-	let cl_field_exc = get_cl (get_type gen (["java";"lang"],"RuntimeException")) in
-	let cl_field_exc_t = TInst (cl_field_exc, []) in
-	let mk_field_exception msg pos = mk (TNew (cl_field_exc, [], [Texpr.Builder.make_string gen.gcon.basic msg pos])) cl_field_exc_t pos in
-
-	let rcf_ctx =
-		ReflectionCFs.new_ctx
-			gen
-			closure_t
-			object_iface
-			false
-			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)
-			(fun hash_array length pos value ->
-				{ hash_array with
-					eexpr = TBinop(OpAssign,
-								hash_array,
-								mk (TCall(rcf_static_insert value.etype, [hash_array; length; pos; value])) hash_array.etype hash_array.epos)
-			})
-			(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 }
-			)
-			None
-			mk_field_exception
-		in
-
-	ReflectionCFs.UniversalBaseClass.configure gen (get_cl (get_type gen (["haxe";"lang"],"HxObject")) ) object_iface dynamic_object;
-
-	ReflectionCFs.configure_dynamic_field_access rcf_ctx;
-
-	ReflectionCFs.implement_varargs_cl rcf_ctx ( get_cl (get_type gen (["haxe";"lang"], "VarArgsBase")) );
-
-	let slow_invoke_field = mk_static_field_access_infer runtime_cl "slowCallField" null_pos [] in
-	let slow_invoke ethis efield eargs =
-		mk (TCall (slow_invoke_field, [ethis; efield; eargs])) t_dynamic ethis.epos
-	in
-	ReflectionCFs.configure rcf_ctx ~slow_invoke:slow_invoke object_iface;
-
-	ObjectDeclMap.configure gen (ReflectionCFs.implement_dynamic_object_ctor rcf_ctx dynamic_object);
-
-	InitFunction.configure gen;
-	TArrayTransform.configure gen (
-	fun e _ ->
-		match e.eexpr with
-			| TArray ({ eexpr = TLocal { v_extra = Some({v_params = _ :: _}) } }, _) -> (* captured transformation *)
-				false
-			| TArray(e1, e2) ->
-				( match run_follow gen (follow e1.etype) with
-					| TInst({ cl_path = (["java"], "NativeArray") }, _) -> false
-					| _ -> true )
-			| _ -> die "" __LOC__
-	) "__get" "__set";
-
-	let field_is_dynamic is_dynamic t field =
-		match field_access_esp gen (gen.greal_type t) field with
-			| FClassField (cl,p,_,_,_,t,_) ->
-				let p = change_param_type (TClassDecl cl) p in
-				is_dynamic (apply_params cl.cl_params p t)
-			| FEnumField _ -> false
-			| _ -> true
-	in
-
-	let is_type_param e = match follow e with
-		| TInst( { cl_kind = KTypeParameter _ },[]) -> true
-		| _ -> false
-	in
-
-	let is_dynamic_expr is_dynamic e =
-		is_dynamic e.etype || match e.eexpr with
-		| TField(tf, f) ->
-			field_is_dynamic is_dynamic tf.etype f
-		| _ ->
-			false
-	in
-
-	let is_dynamic_op t =
-		is_dynamic t || is_boxed_type (gen.greal_type t)
-	in
-
-	let may_nullable t = match gen.gfollow#run_f t with
-		| TAbstract({ a_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
-				| t when is_java_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 nullable_basic t = match gen.gfollow#run_f t with
-		| TAbstract({ a_path = ([],"Null") }, [t])
-		| TType({ t_path = ([],"Null") }, [t]) when is_java_basic_type t ->
-			Some(t)
-		| _ ->
-			None
-	in
-
-	DynamicOperators.configure gen
-		~handle_strings:true
-		(fun e -> match e.eexpr with
-			| TBinop (Ast.OpEq, e1, e2) ->
-				is_dynamic_op e1.etype || is_dynamic_op e2.etype || is_type_param e1.etype || is_type_param e2.etype
-			| TBinop (Ast.OpAdd, e1, e2)
-			| TBinop (Ast.OpNotEq, e1, e2) -> is_dynamic_op e1.etype || is_dynamic_op e2.etype || is_type_param e1.etype || is_type_param e2.etype
-			| TBinop (Ast.OpLt, e1, e2)
-			| TBinop (Ast.OpLte, e1, e2)
-			| TBinop (Ast.OpGte, e1, e2)
-			| TBinop (Ast.OpGt, e1, e2) ->
-				is_dynamic_op e.etype || is_dynamic_op e1.etype || is_dynamic_op e2.etype || is_string e1.etype || is_string e2.etype
-			| TBinop (_, e1, e2) -> is_dynamic_op e.etype || is_dynamic_expr is_dynamic_op e1 || is_dynamic_expr is_dynamic_op e2
-			| TUnop (_, _, e1) ->
-				is_dynamic_expr is_dynamic_op e1
-			| _ -> false)
-		(fun e1 e2 ->
-			let is_null e = match e.eexpr with | TConst(TNull) | TIdent "__undefined__" -> true | _ -> false in
-
-			match e1.eexpr, e2.eexpr with
-				| TConst c1, TConst c2 when is_null e1 || is_null e2 ->
-					{ e1 with eexpr = TConst(TBool (c1 = c2)); etype = basic.tbool }
-				| _ when (is_null e1 || is_null e2) && not (is_java_basic_type e1.etype || is_java_basic_type e2.etype) ->
-					{ e1 with eexpr = TBinop(Ast.OpEq, e1, e2); etype = basic.tbool }
-				| _ ->
-				let is_ref = match follow e1.etype, follow e2.etype with
-					| TDynamic _, _
-					| _, TDynamic _
-					| TAbstract ({ a_path = ([], "Float") },[]) , _
-					| TInst( { cl_path = (["haxe"], "Int32") }, [] ), _
-					| TInst( { cl_path = (["haxe"], "Int64") }, [] ), _
-					| TAbstract ({ a_path = ([], "Int") },[]) , _
-					| TAbstract ({ a_path = ([], "Bool") },[]) , _
-					| _, TAbstract ({ a_path = ([], "Float") },[])
-					| _, TAbstract ({ a_path = ([], "Int") },[])
-					| _, TInst( { cl_path = (["haxe"], "Int32") }, [] )
-					| _, TInst( { cl_path = (["haxe"], "Int64") }, [] )
-					| _, TAbstract ({ a_path = ([], "Bool") },[])
-					| TInst( { cl_kind = KTypeParameter _ }, [] ), _
-					| _, TInst( { cl_kind = KTypeParameter _ }, [] ) -> false
-					| _, _ -> true
-				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 }
-				| _ ->
-					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 op e e1 e2 ->
-				match nullable_basic e1.etype, nullable_basic e2.etype with
-					| Some(t1), None when is_java_basic_type e2.etype ->
-						{ e with eexpr = TBinop(op, mk_cast t1 e1, e2) }
-					| None, Some(t2) when is_java_basic_type e1.etype ->
-						{ e with eexpr = TBinop(op, e1, mk_cast t2 e2) }
-					| _ ->
-							let handler = if is_string e1.etype then begin
-									{ e1 with eexpr = TCall(mk_field_access gen e1 "compareTo" e1.epos, [ 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
-							in
-							let zero = Texpr.Builder.make_int gen.gcon.basic 0 e.epos in
-							{ e with eexpr = TBinop(op, handler, zero) }
-			);
-
-	let closure_cl = get_cl (get_type gen (["haxe";"lang"],"Closure")) in
-	FilterClosures.configure gen (fun e1 s -> true) (ReflectionCFs.get_closure_func rcf_ctx closure_cl);
-
-	ClassInstance.configure gen;
-
-	CastDetect.configure gen (Some empty_ctor_type) false;
-
-	SwitchToIf.configure gen (fun e ->
-		match e.eexpr with
-			| TSwitch(cond, cases, def) ->
-				(match gen.gfollow#run_f cond.etype with
-					| TInst( { cl_path = (["haxe"], "Int32") }, [] )
-					| 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
-				)
-			| _ -> die "" __LOC__
-	);
-
-	ExpressionUnwrap.configure gen;
-
-	(* UnnecessaryCastsRemoval.configure gen; *)
-
-	IntDivisionSynf.configure gen;
-
-	UnreachableCodeEliminationSynf.configure gen true;
-
-	ArraySpliceOptimization.configure gen;
-
-	ArrayDeclSynf.configure gen native_arr_cl change_param_type;
-
-	JavaSpecificSynf.configure gen runtime_cl;
-	JavaSpecificESynf.configure gen runtime_cl;
-
-	(* add native String as a String superclass *)
-	let str_cl = match gen.gcon.basic.tstring with | TInst(cl,_) -> cl | _ -> die "" __LOC__ in
-	str_cl.cl_super <- Some (get_cl (get_type gen (["haxe";"lang"], "NativeString")), []);
-
-	Path.mkdir_from_path (gen.gcon.file ^ "/src");
-
-	let out_files = ref [] in
-
-	(* add resources array *)
-	let res = ref [] in
-	Hashtbl.iter (fun name v ->
-		res := { eexpr = TConst(TString name); etype = gen.gcon.basic.tstring; epos = null_pos } :: !res;
-		let name = Codegen.escape_res_name name true in
-		let full_path = gen.gcon.file ^ "/src/" ^ name in
-		Path.mkdir_from_path full_path;
-
-		let f = open_out_bin full_path in
-		output_string f v;
-		close_out f;
-
-		out_files := (gen.gcon.file_keys#get full_path) :: !out_files
-	) gen.gcon.resources;
-	(try
-		let c = get_cl (Hashtbl.find gen.gtypes (["haxe"], "Resource")) in
-		let cf = PMap.find "content" c.cl_statics in
-		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;
-
-	RenameTypeParameters.run gen.gtypes_list;
-
-	let parts = Str.split_delim (Str.regexp "[\\/]+") gen.gcon.file in
-	Path.mkdir_recursive "" parts;
-
-	let source_dir = gen.gcon.file ^ "/src" in
-	List.iter (fun md ->
-		let w = SourceWriter.new_source_writer () in
-		let should_write = module_type_gen w md in
-		if should_write then begin
-			let path = change_path (t_path md) in
-			write_file gen w (source_dir ^ "/" ^ (String.concat "/" (fst path))) path "java" out_files;
-		end
-	) gen.gtypes_list;
-
-	if not (Common.defined gen.gcon Define.KeepOldOutput) then
-		clean_files gen (gen.gcon.file ^ "/src") !out_files gen.gcon.verbose;
-
-	let path_s_desc path = path_s path [] in
-	dump_descriptor gen ("hxjava_build.txt") path_s_desc (fun md -> path_s_desc (t_infos md).mt_path);
-	if ( not (Common.defined gen.gcon Define.NoCompilation) ) then begin
-		let old_dir = Sys.getcwd() in
-		Sys.chdir gen.gcon.file;
-		let cmd = "haxelib" in
-		let args = ["run";"hxjava";"hxjava_build.txt";"--haxe-version";(string_of_int gen.gcon.version);"--feature-level";"1"] in
-		let args =
-			match gen.gentry_point with
-			| Some (name,_,_) ->
-				let name = if gen.gcon.debug then name ^ "-Debug" else name in
-				args @ ["--out";gen.gcon.file ^ "/" ^ name]
-			| _ ->
-				args
-		in
-		print_endline (cmd ^ " " ^ (String.concat " " args));
-		if gen.gcon.run_command_args cmd args <> 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

+ 17 - 1
src/generators/genshared.ml

@@ -28,6 +28,22 @@ type 'a path_field_mapping = {
 let count_fields pm =
 	PMap.fold (fun _ i -> i + 1) pm 0
 
+let rec replace_mono t =
+	match t with
+	| TMono t ->
+		(match t.tm_type with
+		| None -> Monomorph.bind t t_dynamic
+		| Some _ -> ())
+	| TEnum (_,p) | TInst (_,p) | TType (_,p) | TAbstract (_,p) ->
+		List.iter replace_mono p
+	| TFun (args,ret) ->
+		List.iter (fun (_,_,t) -> replace_mono t) args;
+		replace_mono ret
+	| TAnon _
+	| TDynamic _ -> ()
+	| TLazy f ->
+		replace_mono (lazy_type f)
+
 let pfm_of_typedef td = match follow td.t_type with
 	| TAnon an -> {
 		pfm_path = td.t_path;
@@ -153,7 +169,7 @@ object(self)
 			self#identify accept_anons (lazy_type f)
 		| TAnon an when accept_anons && not (PMap.is_empty an.a_fields) ->
 			let arity = PMap.fold (fun cf i ->
-				Gencommon.replace_mono cf.cf_type;
+				replace_mono cf.cf_type;
 				i + 1
 			) an.a_fields 0 in
 			begin try