Pārlūkot izejas kodu

add TEnumIndex and make matcher generate that instead of Type.enumIndex call (#6364)

Dan Korostelev 8 gadi atpakaļ
vecāks
revīzija
94809e3dc6

+ 1 - 1
src/display/display.ml

@@ -452,7 +452,7 @@ module Diagnostics = struct
 				()
 			| TConst _ | TLocal _ | TTypeExpr _ | TFunction _ when not in_value ->
 				no_effect e.epos;
-			| TConst _ | TLocal _ | TTypeExpr _ | TEnumParameter _ | TVar _ ->
+			| TConst _ | TLocal _ | TTypeExpr _ | TEnumParameter _ | TEnumIndex _ | TVar _ ->
 				()
 			| TFunction tf ->
 				loop false tf.tf_expr

+ 1 - 1
src/generators/codegen.ml

@@ -526,7 +526,7 @@ let rec constructor_side_effects e =
 		true
 	| TField (_,FEnum _) ->
 		false
-	| TUnop _ | TArray _ | TField _ | TEnumParameter _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ ->
+	| TUnop _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TCall _ | TNew _ | TFor _ | TWhile _ | TSwitch _ | TReturn _ | TThrow _ ->
 		true
 	| TBinop _ | TTry _ | TIf _ | TBlock _ | TVar _
 	| TFunction _ | TArrayDecl _ | TObjectDecl _

+ 4 - 0
src/generators/genas3.ml

@@ -633,6 +633,9 @@ and gen_expr ctx e =
 		gen_expr ctx e1;
 		spr ctx ")";
 		gen_field_access ctx e1.etype (field_name s)
+	| TEnumIndex e ->
+		gen_value ctx e;
+		print ctx ".index";
 	| TEnumParameter (e,_,i) ->
 		gen_value ctx e;
 		print ctx ".params[%i]" i;
@@ -882,6 +885,7 @@ and gen_value ctx e =
 	| TBinop _
 	| TField _
 	| TEnumParameter _
+	| TEnumIndex _
 	| TTypeExpr _
 	| TParenthesis _
 	| TObjectDecl _

+ 9 - 3
src/generators/gencommon/enumToClass.ml

@@ -253,7 +253,7 @@ struct
 	let name = "enum_to_class_exprf"
 	let priority = solve_deps name [DBefore TArrayTransform.priority]
 
-	let configure gen t opt_get_native_enum_tag =
+	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
@@ -265,6 +265,12 @@ struct
 			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
@@ -289,7 +295,7 @@ struct
 
 end;;
 
-let configure gen opt_get_native_enum_tag convert_all convert_if_has_meta enum_base_class param_enum_class =
+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 opt_get_native_enum_tag
+	EnumToClassExprf.configure gen t mk_enum_index_call

+ 17 - 9
src/generators/gencommon/enumToClass2.ml

@@ -337,7 +337,7 @@ end;;
 
 
 module EnumToClass2Exprf = struct
-	let init com ec_tbl =
+	let init com ec_tbl mk_enum_index_call =
 		let v_as = alloc_var "__as__" t_dynamic in
 		let rec run e =
 			let get_converted_enum_classes et =
@@ -347,14 +347,22 @@ module EnumToClass2Exprf = struct
 				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
+				Codegen.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
-					let cl = (get_converted_enum_classes f.etype).base in
-					let e_enum = { f with etype = TInst (cl, []) } in
-					Codegen.field e_enum "_hx_index" com.basic.tint e.epos
+					mk_converted_enum_index_access f
 				with Not_found ->
 					{ e with eexpr = TCall(left, [f]) })
 			| TEnumParameter(f, ef, i) ->
@@ -381,12 +389,12 @@ module EnumToClass2Exprf = struct
 	let name = "enum_to_class2_exprf"
 	let priority = solve_deps name []
 
-	let configure gen ec_tbl =
-		let run = init gen.gcon ec_tbl in
+	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 =
+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;
+	EnumToClass2Exprf.configure gen ec_tbl mk_enum_index_call;

+ 1 - 0
src/generators/gencommon/expressionUnwrap.ml

@@ -226,6 +226,7 @@ let rec shallow_expr_type expr : shallow_expr_type =
 		| TBinop _
 		| TField _
 		| TEnumParameter _
+		| TEnumIndex _
 		| TTypeExpr _
 		| TObjectDecl _
 		| TArrayDecl _

+ 1 - 0
src/generators/gencommon/switchToIf.ml

@@ -124,6 +124,7 @@ let configure gen (should_convert:texpr->bool) =
 			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

+ 16 - 9
src/generators/gencpp.ml

@@ -2338,7 +2338,7 @@ let is_gc_element ctx member_type =
    | TCppWrapped _
    | TCppScalarArray _
    | TCppInst _
-   | TCppInterface _ 
+   | TCppInterface _
    | TCppClass
        -> true
    | _ -> false
@@ -2423,6 +2423,10 @@ let retype_expression ctx request_type function_args function_type expression_tr
             let retypedObj = retype TCppDynamic enumObj in
             CppEnumParameter( retypedObj, enumField, enumIndex ), cpp_cast_variant_type_of (cpp_type_of (get_nth_type enumField enumIndex))
 
+         | TEnumIndex enumObj ->
+            let retypedObj = retype TCppDynamic enumObj in
+            CppEnumIndex retypedObj, TCppScalar "int"
+
          | TConst TThis ->
             uses_this := Some !this_real;
             CppThis(!this_real), if !this_real=ThisDynamic then TCppDynamic else cpp_type_of expr.etype
@@ -3162,7 +3166,7 @@ let retype_expression ctx request_type function_args function_type expression_tr
             Using the 'typedef hack', where we use typedef X<T> = T, allows the
             haxe compiler to use these types interchangeably. We then work
             out the correct way to convert between them when one is expected, but another provided.
- 
+
             TCppFunction: these do not really interact with the haxe function type, T
             Since they are implemented with cpp::Function, conversion to/from Dynamic should happen automatically
                CallableData<T> = T;
@@ -3394,9 +3398,9 @@ let gen_cpp_ast_expression_tree ctx class_name func_name function_args function_
 
       | CppEnumIndex(obj) ->
          gen obj;
-         (*if cpp_is_dynamic_type obj.cpptype then*)
+         if cpp_is_dynamic_type obj.cpptype then
             out ".StaticCast< ::hx::EnumBase >()";
-         out "->getIndex()"
+         out "->_hx_getIndex()"
 
       | CppNullAccess -> out ("hx::Throw(" ^ strq "Null access" ^ ")")
       | CppFunction(func,_) ->
@@ -6233,7 +6237,7 @@ let generate_class_files baseCtx super_deps constructor_deps class_def inScripta
          List.iter dump_script_static class_def.cl_ordered_statics;
 
          output_cpp "static hx::ScriptNamedFunction __scriptableFunctions[] = {\n";
-         let dump_func f isStaticFlag = 
+         let dump_func f isStaticFlag =
             let s = try Hashtbl.find sigs f.cf_name with Not_found -> "v" in
             output_cpp ("  hx::ScriptNamedFunction(\"" ^ f.cf_name ^ "\",__s_" ^ f.cf_name ^ ",\"" ^ s ^ "\", " ^ isStaticFlag ^ " ),\n" )
          in
@@ -7559,6 +7563,9 @@ class script_writer ctx filename asciiOut =
          in
          this#write ( (this#op IaEnumI) ^ (this#typeText (TEnum(enum,[])) ) ^ (string_of_int i) ^ "\n");
          this#gen_expression expr;
+   | TEnumIndex expr ->
+         this#write ( (this#op IaCallMember) ^ (this#typeTextString "hx::EnumBase") ^ " " ^ (this#stringText "__Index") ^ "0" ^ (this#commentOf ("Enum index") ) ^ "\n");
+         this#gen_expression expr;
    | TSwitch (condition,cases,optional_default)  ->
          this#write ( (this#op IaSwitch) ^ (string_of_int (List.length cases)) ^ " " ^
                            (match optional_default with None -> "0" | Some _ -> "1") ^ "\n");
@@ -7743,7 +7750,7 @@ class script_writer ctx filename asciiOut =
             gen_expression e;
 
          | CppCompare(_, left, right, op) ->
-            this#writeOpLine (IaBinOp op); 
+            this#writeOpLine (IaBinOp op);
             gen_expression left;
             gen_expression right;
 
@@ -7870,7 +7877,7 @@ class script_writer ctx filename asciiOut =
          | CppCastScalar(expr,_) -> match_expr expr
          | CppCastVariant(expr) -> match_expr expr
          | CppCastStatic(expr,_) -> match_expr expr
-         | CppNullAccess -> 
+         | CppNullAccess ->
             this#writeOpLine IaThrow;
             this#begin_expr;
             this#writeCppPos expression;
@@ -8137,13 +8144,13 @@ let generate_source ctx =
                let id = gen_hash32 seed class_name in
                (* reserve first 100 ids for runtime *)
                if id < Int32.of_int 100 || Hashtbl.mem existingIds id then
-                  makeId class_name (seed+100) 
+                  makeId class_name (seed+100)
                else begin
                   Hashtbl.add existingIds id true;
                   Hashtbl.add ctx.ctx_type_ids class_name id;
                end in
             makeId name 0;
- 
+
             build_xml := !build_xml ^ (get_class_code class_def Meta.BuildXml);
             if (has_init_field class_def) then
                init_classes := class_def.cl_path ::  !init_classes;

+ 6 - 1
src/generators/gencs.ml

@@ -1654,6 +1654,7 @@ let generate con =
 					| TObjectDecl _ -> write w "[ obj decl not supported ]"; if !strict_mode then assert false
 					| TFunction _ -> write w "[ func decl not supported ]"; if !strict_mode then assert false
 					| TEnumParameter _ -> write w "[ enum parameter not supported ]"; if !strict_mode then assert false
+					| TEnumIndex _ -> write w "[ enum index not supported ]"; if !strict_mode then assert false
 			)
 			and do_call w e el =
 				let params, el = extract_tparams [] el in
@@ -2727,7 +2728,11 @@ let generate con =
 		ClosuresToClass.configure gen closure_t;
 
 		let enum_base = (get_cl (get_type gen (["haxe";"lang"],"Enum")) ) in
-		EnumToClass2.configure gen enum_base;
+		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;
 

+ 2 - 0
src/generators/genhl.ml

@@ -1915,6 +1915,8 @@ and eval_expr ctx e =
 			r
 		| _ ->
 			abort ("Unknown native call " ^ v.v_name) e.epos)
+	| TEnumIndex v ->
+		get_enum_index ctx v
 	| TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Type" },{ cf_name = "enumIndex" })) },[{ eexpr = TCast(v,_) }]) when (match follow v.etype with TEnum _ -> true | _ -> false) ->
 		get_enum_index ctx v
 	| TCall ({ eexpr = TField (_,FStatic ({ cl_path = [],"Type" },{ cf_name = "enumIndex" })) },[v]) when (match follow v.etype with TEnum _ -> true | _ -> false) ->

+ 6 - 1
src/generators/genjava.ml

@@ -1612,6 +1612,7 @@ let generate con =
 				| TObjectDecl _ -> write w "[ obj decl not supported ]"; if !strict_mode then assert false
 				| TFunction _ -> write w "[ func decl not supported ]"; if !strict_mode then assert false
 				| TEnumParameter _ -> write w "[ enum parameter not supported ]"; if !strict_mode then assert false
+				| TEnumIndex _ -> write w "[ enum index not supported ]"; if !strict_mode then assert false
 		in
 		expr_s w e
 	in
@@ -2105,7 +2106,11 @@ let generate con =
 
 	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
-	EnumToClass.configure gen (None) false true enum_base param_enum_base;
+	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;
 

+ 4 - 0
src/generators/genjs.ml

@@ -500,6 +500,9 @@ and gen_expr ctx e =
 			print ctx "($_=";
 			gen_value ctx x;
 			print ctx ",$bind($_,$_%s))" (if Meta.has Meta.SelfCall f.cf_meta then "" else (field f.cf_name)))
+	| TEnumIndex x ->
+		gen_value ctx x;
+		print ctx "[1]"
 	| TEnumParameter (x,_,i) ->
 		gen_value ctx x;
 		print ctx "[%i]" (i + 2)
@@ -865,6 +868,7 @@ and gen_value ctx e =
 	| TBinop _
 	| TField _
 	| TEnumParameter _
+	| TEnumIndex _
 	| TTypeExpr _
 	| TParenthesis _
 	| TObjectDecl _

+ 4 - 0
src/generators/genlua.ml

@@ -543,6 +543,9 @@ and gen_expr ?(local=true) ctx e = begin
 	| TEnumParameter (x,_,i) ->
 		gen_value ctx x;
 		print ctx "[%i]" (i + 2)
+	| TEnumIndex x ->
+		gen_value ctx x;
+		print ctx "[1]"
 	| TField (x, (FInstance(_,_,f) | FStatic(_,f) | FAnon(f))) when Meta.has Meta.SelfCall f.cf_meta ->
 		gen_value ctx x;
 	| TField ({ eexpr = TConst(TInt _ | TFloat _| TString _| TBool _) } as e , ((FInstance _ | FAnon _) as ef)) ->
@@ -1041,6 +1044,7 @@ and gen_value ctx e =
 	| TBinop _
 	| TField _
 	| TEnumParameter _
+	| TEnumIndex _
 	| TTypeExpr _
 	| TParenthesis _
 	| TObjectDecl _

+ 2 - 0
src/generators/genneko.ml

@@ -248,6 +248,8 @@ and gen_expr ctx e =
 		| _ -> assert false)
 	| TEnumParameter (e,_,i) ->
 		EArray (field p (gen_expr ctx e) "args",int p i),p
+	| TEnumIndex e ->
+		field p (gen_expr ctx e) "index"
 	| TField (e,f) ->
 		field p (gen_expr ctx e) (field_name f)
 	| TTypeExpr t ->

+ 6 - 0
src/generators/genphp.ml

@@ -1316,6 +1316,11 @@ and gen_expr ctx e =
 		gen_value ctx e1;
 		spr ctx ")";
 		print ctx "->params[%d]" i;
+	| TEnumIndex e1 ->
+		spr ctx "_hx_deref(";
+		gen_value ctx e1;
+		spr ctx ")";
+		print ctx "->index";
 	| TField (e1,s) ->
 		gen_tfield ctx e e1 s
 	| TTypeExpr t ->
@@ -1804,6 +1809,7 @@ and gen_value ctx e =
 	| TArray _
 	| TBinop _
 	| TEnumParameter _
+	| TEnumIndex _
 	| TField _
 	| TParenthesis _
 	| TObjectDecl _

+ 10 - 0
src/generators/genphp7.ml

@@ -1611,6 +1611,7 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 				| TCast (expr, mtype) -> self#write_expr_cast expr mtype
 				| TMeta (_, expr) -> self#write_expr expr
 				| TEnumParameter (expr, constructor, index) -> self#write_expr_enum_parameter expr constructor index
+				| TEnumIndex expr -> self#write_expr_enum_index expr
 			);
 			expr_hierarchy <- List.tl expr_hierarchy
 		(**
@@ -2740,6 +2741,15 @@ class code_writer (ctx:Common.context) hx_type_path php_name =
 				| _ -> self#write_expr expr
 			);
 			self#write ("->params[" ^ (string_of_int index) ^ "]")
+		(**
+			Write TEnumIndex expression to output buffer
+		*)
+		method write_expr_enum_index expr =
+			(match expr.eexpr with
+				| TConst TNull -> self#write "(null)"
+				| _ -> self#write_expr expr
+			);
+			self#write "->index"
 		(**
 			Writes argument for function declarations or calls
 		*)

+ 6 - 0
src/generators/genpy.ml

@@ -713,6 +713,10 @@ module Transformer = struct
 			let e1 = trans true [] e1 in
 			let p = { ae.a_expr with eexpr = TEnumParameter(e1.a_expr,ef,i)} in
 			lift true e1.a_blocks p
+		| (_, TEnumIndex e1) ->
+			let e1 = trans true [] e1 in
+			let p = { ae.a_expr with eexpr = TEnumIndex e1.a_expr } in
+			lift true e1.a_blocks p
 		| (true, TIf(econd, eif, eelse)) ->
 			(let econd1 = trans true [] econd in
 			let eif1 = trans true [] eif in
@@ -1189,6 +1193,8 @@ module Printer = struct
 				handle_keywords v.v_name
 			| TEnumParameter(e1,_,index) ->
 				Printf.sprintf "%s.params[%i]" (print_expr pctx e1) index
+			| TEnumIndex e1 ->
+				Printf.sprintf "%s.index" (print_expr pctx e1)
 			| TArray(e1,e2) when (is_type1 "" "list")(e1.etype) || is_underlying_array e1.etype ->
 				print_tarray_list pctx e1 e2
 			| TArray({etype = t} as e1,e2) when is_anon_or_dynamic t ->

+ 4 - 0
src/generators/genswf9.ml

@@ -882,6 +882,9 @@ let rec gen_access ctx e (forset : 'a) : 'a access =
 		write ctx (HGetProp (ident "params"));
 		write ctx (HSmallInt i);
 		VArray
+	| TEnumIndex e1 ->
+		gen_expr ctx true e1;
+		VId (ident "index")
 	| TField (e1,fa) ->
 		let f = field_name fa in
 		let id, k, closure = property ctx f e1.etype in
@@ -1060,6 +1063,7 @@ let rec gen_expr_content ctx retval e =
 		no_value ctx retval
 	| TField _
 	| TLocal _
+	| TEnumIndex _
 	| TTypeExpr _ ->
 		getvar ctx (gen_access ctx e Read)
 	(* both accesses return dynamic so let's cast them to the real type *)

+ 4 - 0
src/macro/eval/evalJit.ml

@@ -303,6 +303,7 @@ and jit_expr jit return e =
 		if l < 256 then begin
 			let cases = Array.init l (fun i -> try IntMap.find (i + !shift) !h with Not_found -> exec_def) in
 			if !shift = 0 then begin match (Texpr.skip e1).eexpr with
+				| TEnumIndex e1
 				| TCall({eexpr = TField(_,FStatic({cl_path=[],"Type"},{cf_name="enumIndex"}))},[e1]) ->
 					let exec = jit_expr jit false e1 in
 					emit_enum_switch_array exec cases exec_def e1.epos
@@ -724,6 +725,9 @@ and jit_expr jit return e =
 	| TEnumParameter(e1,_,i) ->
 		let exec = jit_expr jit false e1 in
 		emit_enum_parameter_read exec i
+	| TEnumIndex e1 ->
+		let exec = jit_expr jit false e1 in
+		emit_enum_index exec
 	(* ops *)
 	| TBinop(OpEq,e1,{eexpr = TConst TNull}) | TBinop(OpEq,{eexpr = TConst TNull},e1) ->
 		let exec = jit_expr jit false e1 in

+ 2 - 0
src/macro/macroApi.ml

@@ -1204,6 +1204,7 @@ and encode_texpr e =
 			| TCast(e1,mt) -> 24,[loop e1;match mt with None -> vnull | Some mt -> encode_module_type mt]
 			| TMeta(m,e1) -> 25,[encode_meta_entry m;loop e1]
 			| TEnumParameter(e1,ef,i) -> 26,[loop e1;encode_efield ef;vint i]
+			| TEnumIndex e1 -> 27,[loop e1]
 		in
 		encode_obj OTypedExprDef [
 			"pos", encode_pos e.epos;
@@ -1350,6 +1351,7 @@ and decode_texpr v =
 		| 24, [v1;mto] -> TCast(loop v1,opt decode_module_type mto)
 		| 25, [m;v1] -> TMeta(decode_meta_entry m,loop v1)
 		| 26, [v1;ef;i] -> TEnumParameter(loop v1,decode_efield ef,decode_int i)
+		| 27, [v1] -> TEnumIndex(loop v1)
 		| i,el -> Printf.printf "%i %i\n" i (List.length el); raise Invalid_expr
 	in
 	try

+ 6 - 1
src/optimization/analyzer.ml

@@ -420,6 +420,11 @@ module ConstPropagation = DataFlow(struct
 					| EnumValue(_,el) -> (try List.nth el i with Failure _ -> raise Exit)
 					| _ -> raise Exit
 				end;
+			| TEnumIndex e1 ->
+				begin match eval bb e1 with
+					| EnumValue(i,_) -> Const (TInt (Int32.of_int i))
+					| _ -> raise Exit
+				end;
 			| TCall ({ eexpr = TField (_,FStatic({cl_path=[],"Type"} as c,({cf_name="enumIndex"} as cf)))},[e1]) when ctx.com.platform = Eval ->
 				begin match follow e1.etype,eval bb e1 with
 					| TEnum _,EnumValue(i,_) -> Const (TInt (Int32.of_int i))
@@ -606,7 +611,7 @@ module LocalDce = struct
 			| TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit
 			| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit
 			| TFor _ -> raise Exit
-			| TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _
+			| TArray _ | TEnumParameter _ | TEnumIndex _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _
 			| TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e
 		in
 		try

+ 3 - 1
src/optimization/analyzerTexpr.ml

@@ -264,6 +264,8 @@ module TexprKindMapper = struct
 			{ e with eexpr = TThrow (f KThrow e1) }
 		| TEnumParameter (e1,ef,i) ->
 			{ e with eexpr = TEnumParameter(f KAccess e1,ef,i) }
+		| TEnumIndex e1 ->
+			{ e with eexpr = TEnumIndex (f KAccess e1) }
 		| TField (e1,v) ->
 			{ e with eexpr = TField (f KAccess e1,v) }
 		| TParenthesis e1 ->
@@ -645,7 +647,7 @@ module Fusion = struct
 				state#dec_reads v;
 				block_element acc el
 			(* no-side-effect *)
-			| {eexpr = TEnumParameter _ | TFunction _ | TConst _ | TTypeExpr _} :: el ->
+			| {eexpr = TEnumParameter _ | TEnumIndex _ | TFunction _ | TConst _ | TTypeExpr _} :: el ->
 				block_element acc el
 			| {eexpr = TMeta((Meta.Pure,_,_),_)} :: el ->
 				block_element acc el

+ 4 - 1
src/optimization/analyzerTexprTransformer.ml

@@ -159,6 +159,9 @@ let rec func ctx bb tf t p =
 		| TEnumParameter(e1,ef,ei) ->
 			let bb,e1 = value bb e1 in
 			bb,{e with eexpr = TEnumParameter(e1,ef,ei)}
+		| TEnumIndex e1 ->
+			let bb,e1 = value bb e1 in
+			bb,{e with eexpr = TEnumIndex e1}
 		| TFunction tf ->
 			let bb_func,bb_func_end = func ctx bb tf e.etype e.epos in
 			let e_fun = mk (TConst (TString "fun")) t_dynamic p in
@@ -603,7 +606,7 @@ let rec func ctx bb tf t p =
 			add_texpr bb e;
 			bb
 		(* no-side-effect *)
-		| TEnumParameter _ | TFunction _ | TConst _ | TTypeExpr _ | TLocal _ ->
+		| TEnumParameter _ | TEnumIndex _ | TFunction _ | TConst _ | TTypeExpr _ | TLocal _ ->
 			bb
 		(* no-side-effect composites *)
 		| TParenthesis e1 | TMeta(_,e1) | TCast(e1,None) | TField(e1,_) | TUnop(_,_,e1) ->

+ 3 - 1
src/optimization/optimizer.ml

@@ -927,7 +927,7 @@ let standard_precedence op =
 
 let rec need_parent e =
 	match e.eexpr with
-	| TConst _ | TLocal _ | TArray _ | TField _ | TEnumParameter _ | TParenthesis _ | TCall _ | TNew _ | TTypeExpr _ | TObjectDecl _ | TArrayDecl _ -> false
+	| TConst _ | TLocal _ | TArray _ | TField _ | TEnumParameter _ | TEnumIndex _ | TParenthesis _ | TCall _ | TNew _ | TTypeExpr _ | TObjectDecl _ | TArrayDecl _ -> false
 	| TCast (e,None) | TMeta(_,e) -> need_parent e
 	| TCast _ | TThrow _ | TReturn _ | TTry _ | TSwitch _ | TFor _ | TIf _ | TWhile _ | TBinop _ | TContinue | TBreak
 	| TBlock _ | TVar _ | TFunction _ | TUnop _ -> true
@@ -1019,6 +1019,8 @@ let sanitize_expr com e =
 		if need_parent e2 then { e with eexpr = TCall(parent e2,args) } else e
 	| TEnumParameter (e2,ef,i) ->
 		if need_parent e2 then { e with eexpr = TEnumParameter(parent e2,ef,i) } else e
+	| TEnumIndex e2 ->
+		if need_parent e2 then { e with eexpr = TEnumIndex(parent e2) } else e
 	| TField (e2,f) ->
 		if need_parent e2 then { e with eexpr = TField(parent e2,f) } else e
 	| TArray (e1,e2) ->

+ 1 - 1
src/optimization/optimizerTexpr.ml

@@ -69,7 +69,7 @@ let has_side_effect e =
 		| TNew(c,_,el) when (match c.cl_constructor with Some cf when PurityState.is_pure c cf -> true | _ -> false) -> List.iter loop el
 		| TNew _ | TCall _ | TBinop ((OpAssignOp _ | OpAssign),_,_) | TUnop ((Increment|Decrement),_,_) -> raise Exit
 		| TReturn _ | TBreak | TContinue | TThrow _ | TCast (_,Some _) -> raise Exit
-		| TArray _ | TEnumParameter _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _
+		| TArray _ | TEnumParameter _ | TEnumIndex _ | TCast (_,None) | TBinop _ | TUnop _ | TParenthesis _ | TMeta _ | TWhile _ | TFor _
 		| TField _ | TIf _ | TTry _ | TSwitch _ | TArrayDecl _ | TBlock _ | TObjectDecl _ | TVar _ -> Type.iter loop e
 	in
 	try

+ 1 - 2
src/typing/matcher.ml

@@ -1261,8 +1261,7 @@ module TexprConverter = struct
 				   (correctly typed) neutral value because it doesn't actually matter. *)
 				mk (TConst (TInt (Int32.of_int 0))) ctx.t.tint e.epos
 			else
-				let cf = PMap.find "enumIndex" c_type.cl_statics in
-				make_static_call ctx c_type cf (fun t -> t) [e] com.basic.tint e.epos
+				mk (TEnumIndex e) com.basic.tint e.epos
 		in
 		let mk_name_call e =
 			if not ctx.in_macro && not ctx.com.display.DisplayMode.dms_full_typing then

+ 17 - 2
src/typing/type.ml

@@ -138,6 +138,7 @@ and texpr_expr =
 	| TCast of texpr * module_type option
 	| TMeta of metadata_entry * texpr
 	| TEnumParameter of texpr * tenum_field * int
+	| TEnumIndex of texpr
 
 and tfield_access =
 	| FInstance of tclass * tparams * tclass_field
@@ -983,6 +984,7 @@ let s_expr_kind e =
 	| TArray (_,_) -> "Array"
 	| TBinop (_,_,_) -> "Binop"
 	| TEnumParameter (_,_,_) -> "EnumParameter"
+	| TEnumIndex _ -> "EnumIndex"
 	| TField (_,_) -> "Field"
 	| TTypeExpr _ -> "TypeExpr"
 	| TParenthesis _ -> "Parenthesis"
@@ -1029,6 +1031,8 @@ let rec s_expr s_type e =
 		sprintf "%s[%s]" (loop e1) (loop e2)
 	| TBinop (op,e1,e2) ->
 		sprintf "(%s %s %s)" (loop e1) (s_binop op) (loop e2)
+	| TEnumIndex e1 ->
+		sprintf "EnumIndex %s" (loop e1)
 	| TEnumParameter (e1,_,i) ->
 		sprintf "%s[%i]" (loop e1) i
 	| TField (e,f) ->
@@ -1105,6 +1109,7 @@ let rec s_expr_pretty print_var_ids tabs top_level s_type e =
 	| TArray (e1,e2) -> sprintf "%s[%s]" (loop e1) (loop e2)
 	| TBinop (op,e1,e2) -> sprintf "%s %s %s" (loop e1) (s_binop op) (loop e2)
 	| TEnumParameter (e1,_,i) -> sprintf "%s[%i]" (loop e1) i
+	| TEnumIndex e1 -> sprintf "enumIndex %s" (loop e1)
 	| TField (e1,s) -> sprintf "%s.%s" (loop e1) (field_name s)
 	| TTypeExpr mt -> (s_type_path (t_path mt))
 	| TParenthesis e1 -> sprintf "(%s)" (loop e1)
@@ -1188,6 +1193,7 @@ let rec s_expr_ast print_var_ids tabs s_type e =
 	| TBinop (op,e1,e2) -> tag "Binop" [loop e1; s_binop op; loop e2]
 	| TUnop (op,flag,e1) -> tag "Unop" [s_unop op; if flag = Postfix then "Postfix" else "Prefix"; loop e1]
 	| TEnumParameter (e1,ef,i) -> tag "EnumParameter" [loop e1; ef.ef_name; string_of_int i]
+	| TEnumIndex e1 -> tag "EnumIndex" [loop e1]
 	| TField (e1,fa) ->
 		let sfa = match fa with
 			| FInstance(c,tl,cf) -> tag "FInstance" ~extra_tabs:"\t" [s_type (TInst(c,tl)); cf.cf_name]
@@ -2254,6 +2260,7 @@ let iter f e =
 	| TThrow e
 	| TField (e,_)
 	| TEnumParameter (e,_,_)
+	| TEnumIndex e
 	| TParenthesis e
 	| TCast (e,_)
 	| TUnop (_,_,e)
@@ -2309,7 +2316,9 @@ let map_expr f e =
 	| TThrow e1 ->
 		{ e with eexpr = TThrow (f e1) }
 	| TEnumParameter (e1,ef,i) ->
-		 { e with eexpr = TEnumParameter(f e1,ef,i) }
+		{ e with eexpr = TEnumParameter(f e1,ef,i) }
+	| TEnumIndex e1 ->
+		{ e with eexpr = TEnumIndex (f e1) }
 	| TField (e1,v) ->
 		{ e with eexpr = TField (f e1,v) }
 	| TParenthesis e1 ->
@@ -2374,7 +2383,9 @@ let map_expr_type f ft fv e =
 	| TThrow e1 ->
 		{ e with eexpr = TThrow (f e1); etype = ft e.etype }
 	| TEnumParameter (e1,ef,i) ->
-		{ e with eexpr = TEnumParameter(f e1,ef,i); etype = ft e.etype }
+		{ e with eexpr = TEnumParameter (f e1,ef,i); etype = ft e.etype }
+	| TEnumIndex e1 ->
+		{ e with eexpr = TEnumIndex (f e1); etype = ft e.etype }
 	| TField (e1,v) ->
 		let e1 = f e1 in
 		let v = try
@@ -2570,6 +2581,7 @@ module TExprToExpr = struct
 			) cases in
 			let def = match eopt def with None -> None | Some (EBlock [],_) -> Some (None,null_pos) | Some e -> Some (Some e,pos e) in
 			ESwitch (convert_expr e,cases,def)
+		| TEnumIndex _
 		| TEnumParameter _ ->
 			(* these are considered complex, so the AST is handled in TMeta(Meta.Ast) *)
 			assert false
@@ -2741,6 +2753,9 @@ module Texpr = struct
 		| TEnumParameter (e1,ef,i) ->
 			let acc,e1 = f acc e1 in
 			acc,{ e with eexpr = TEnumParameter(e1,ef,i) }
+		| TEnumIndex e1 ->
+			let acc,e1 = f acc e1 in
+			acc,{ e with eexpr = TEnumIndex e1 }
 		| TField (e1,v) ->
 			let acc,e1 = f acc e1 in
 			acc,{ e with eexpr = TField (e1,v) }

+ 1 - 0
std/cs/_std/Type.hx

@@ -325,6 +325,7 @@ enum ValueType {
 		return Std.is(e, cs.system.Enum) ? [] : cast(e,HxEnum).getParams();
 	}
 
+	@:ifFeature("has_enum")
 	@:pure
 	public static function enumIndex( e : EnumValue ) : Int
 	{

+ 5 - 0
std/haxe/macro/Type.hx

@@ -969,6 +969,11 @@ enum TypedExprDef {
 		Access to an enum parameter (generated by the pattern matcher).
 	**/
 	TEnumParameter(e1:TypedExpr, ef:EnumField, index:Int);
+
+	/**
+		Access to an enum index (generated by the pattern matcher).
+	**/
+	TEnumIndex(e1:TypedExpr);
 }
 
 /**

+ 3 - 1
std/haxe/macro/TypedExprTools.hx

@@ -54,6 +54,7 @@ class TypedExprTools {
 			case TWhile(e1, e2, flag): with(e, TWhile(f(e1), f(e2), flag));
 			case TThrow(e1): with(e, TThrow(f(e1)));
 			case TEnumParameter(e1, ef, i): with(e, TEnumParameter(f(e1), ef, i));
+			case TEnumIndex(e1): with(e, TEnumIndex(f(e1)));
 			case TField(e1, fa): with(e, TField(f(e1), fa));
 			case TParenthesis(e1): with(e, TParenthesis(f(e1)));
 			case TUnop(op, pre, e1): with(e, TUnop(op, pre, f(e1)));
@@ -86,7 +87,7 @@ class TypedExprTools {
 			case TArray(e1, e2) | TBinop(_, e1, e2) | TFor(_, e1, e2) | TWhile(e1, e2, _):
 				f(e1);
 				f(e2);
-			case TThrow(e1) | TEnumParameter(e1, _, _) | TField(e1, _) | TParenthesis(e1) | TUnop(_, _, e1) | TCast(e1, _) | TMeta(_, e1):
+			case TThrow(e1) | TEnumParameter(e1, _, _) | TEnumIndex(e1) | TField(e1, _) | TParenthesis(e1) | TUnop(_, _, e1) | TCast(e1, _) | TMeta(_, e1):
 				f(e1);
 			case TArrayDecl(el) | TNew(_, _, el) | TBlock(el):
 				for (e in el) f(e);
@@ -135,6 +136,7 @@ class TypedExprTools {
 			case TWhile(e1, e2, flag): with(e, TWhile(f(e1), f(e2), flag), ft(e.t));
 			case TThrow(e1): with(e, TThrow(f(e1)), ft(e.t));
 			case TEnumParameter(e1, ef, i): with(e, TEnumParameter(f(e1), ef, i), ft(e.t));
+			case TEnumIndex(e1): with(e, TEnumIndex(f(e1)), ft(e.t));
 			case TField(e1, fa): with(e, TField(f(e1), fa), ft(e.t));
 			case TParenthesis(e1): with(e, TParenthesis(e1), ft(e.t));
 			case TUnop(op, pre, e1): with(e, TUnop(op, pre, f(e1)), ft(e.t));

+ 1 - 0
std/java/_std/Type.hx

@@ -407,6 +407,7 @@ enum ValueType {
 		return null;
 	}
 
+	@:ifFeature("has_enum")
 	@:functionCode('
 		if (e instanceof java.lang.Enum)
 			return ((java.lang.Enum) e).ordinal();

+ 4 - 0
tests/unit/src/unit/TestOverloads.hx

@@ -202,9 +202,11 @@ class TestOverloads extends Test
 		eq(child.someField(true, 10), 52);
 		eq(child.initialized3, true);
 
+		#if !cs // TODO: https://github.com/HaxeFoundation/haxe/issues/6352
 		var child:ChildJava4<Int, Bool, ChildJava3<Dynamic, Dynamic>> = new ChildJava4(Bytes.ofString("test"));
 		eq(child.s, "test");
 		eq(child.someField(child), null);
+		#end
 	}
 }
 
@@ -602,9 +604,11 @@ class ChildJava3<A, T : BaseJava> extends ChildJava2<T>
 	}
 }
 
+#if !cs // TODO: https://github.com/HaxeFoundation/haxe/issues/6352
 class ChildJava4<X, Y, Z : ChildJava2<Dynamic>> extends ChildJava3<Y, Z>
 {
 }
+#end
 
 interface NormalInterface
 {