PageRenderTime 66ms CodeModel.GetById 10ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 1ms

/bin/std/Type.hx

http://github.com/Yoomee/clippy
Haxe | 821 lines | 718 code | 29 blank | 74 comment | 212 complexity | 25bf14e847e12f1577f580b5f7a5dc79 MD5 | raw file
  1/**
  2	The diffent possible runtime types of a value.
  3	See [Type] for the haXe Reflection API.
  4**/
  5enum ValueType {
  6	TNull;
  7	TInt;
  8	TFloat;
  9	TBool;
 10	TObject;
 11	TFunction;
 12	TClass( c : Class<Dynamic> );
 13	TEnum( e : Enum<Dynamic> );
 14	TUnknown;
 15}
 16
 17/**
 18	The haXe Reflection API enables you to retreive informations about any value,
 19	Classes and Enums at runtime.
 20**/
 21class Type {
 22
 23	/**
 24		Returns the class of a value or [null] if this value is not a Class instance.
 25	**/
 26	public static function getClass<T>( o : T ) : Class<T> untyped {
 27		#if flash9
 28			var cname = __global__["flash.utils.getQualifiedClassName"](o);
 29			if( cname == "null" || cname == "Object" || cname == "int" || cname == "Number" || cname == "Boolean" )
 30				return null;
 31			if( o.hasOwnProperty("prototype") )
 32				return null;
 33			var c = __as__(__global__["flash.utils.getDefinitionByName"](cname),Class);
 34			if( c.__isenum )
 35				return null;
 36			return c;
 37		#elseif flash
 38			if( o.__enum__ != null )
 39				return null;
 40			return o.__class__;
 41		#elseif js
 42			if( o == null )
 43				return null;
 44			if( o.__enum__ != null )
 45				return null;
 46			return o.__class__;
 47		#elseif neko
 48			if( __dollar__typeof(o) != __dollar__tobject )
 49				return null;
 50			var p = __dollar__objgetproto(o);
 51			if( p == null )
 52				return null;
 53			return p.__class__;
 54		#elseif php
 55			if(o == null) return null;
 56			untyped if(__call__("is_array",  o)) {
 57				if(__call__("count", o) == 2 && __call__("is_callable", o)) return null;
 58				return __call__("_hx_ttype", 'Array');
 59			}
 60			if(untyped __call__("is_string", o)) {
 61				if(__call__("_hx_is_lambda", untyped o)) return null;
 62				return __call__("_hx_ttype", 'String');
 63			}
 64			if(!untyped __call__("is_object", o)) {
 65				return null;
 66			}
 67			var c = __call__("get_class", o);
 68			if(c == false || c == '_hx_anonymous' || __call__("is_subclass_of", c, "enum"))
 69				return null;
 70			else
 71				return __call__("_hx_ttype", c);
 72		#elseif cpp
 73			if (o==null || !Reflect.isObject(o))  return null;
 74			var c = o.__GetClass();
 75			switch(c.toString())
 76			{
 77				case "__Anon" : return null;
 78				case "Class" : return null;
 79			}
 80			return c;
 81		#else
 82			return null;
 83		#end
 84	}
 85
 86	/**
 87		Returns the enum of a value or [null] if this value is not an Enum instance.
 88	**/
 89	public static function getEnum( o : Dynamic ) : Enum<Dynamic> untyped {
 90		#if flash9
 91			var cname = __global__["flash.utils.getQualifiedClassName"](o);
 92			if( cname == "null" || cname.substr(0,8) == "builtin." )
 93				return null;
 94			// getEnum(Enum) should be null
 95			if( o.hasOwnProperty("prototype") )
 96				return null;
 97			var c = __as__(__global__["flash.utils.getDefinitionByName"](cname),Class);
 98			if( !c.__isenum )
 99				return null;
100			return c;
101		#elseif flash
102			return o.__enum__;
103		#elseif js
104			if( o == null )
105				return null;
106			return o.__enum__;
107		#elseif neko
108			if( __dollar__typeof(o) != __dollar__tobject )
109				return null;
110			return o.__enum__;
111		#elseif php
112			if(!__php__("$o instanceof Enum"))
113				return null;
114			else
115				return __php__("_hx_ttype(get_class($o))");
116		#elseif cpp
117			if(o.__GetClass()!=Enum)
118				return null;
119			return o;
120		#else
121			return null;
122		#end
123	}
124
125
126	/**
127		Returns the super-class of a class, or null if no super class.
128	**/
129	public static function getSuperClass( c : Class<Dynamic> ) : Class<Dynamic> untyped {
130		#if flash9
131			var cname = __global__["flash.utils.getQualifiedSuperclassName"](c);
132			if( cname == "Object" )
133				return null;
134			return __as__(__global__["flash.utils.getDefinitionByName"](cname),Class);
135		#elseif php
136			var s = __php__("get_parent_class")(c.__tname__);
137			if(s == false)
138				return null;
139			else
140				return __call__("_hx_ttype", s);
141		#elseif cpp
142			return c.GetSuper();
143		#else
144			return c.__super__;
145		#end
146	}
147
148
149	/**
150		Returns the complete name of a class.
151	**/
152	public static function getClassName( c : Class<Dynamic> ) : String {
153		if( c == null )
154			return null;
155		#if flash9
156			var str : String = untyped __global__["flash.utils.getQualifiedClassName"](c);
157			switch( str ) {
158			case "int": return "Int";
159			case "Number": return "Float";
160			case "Boolean": return "Bool";
161			default:
162			}
163			return str.split("::").join(".");
164		#elseif php
165			return untyped c.__qname__;
166		#elseif cpp
167			return untyped c.mName;
168		#else
169			var a : Array<String> = untyped c.__name__;
170			return a.join(".");
171		#end
172	}
173
174	/**
175		Returns the complete name of an enum.
176	**/
177	public static function getEnumName( e : Enum<Dynamic> ) : String {
178		#if flash9
179			return getClassName(cast e);
180		#elseif php
181			return untyped e.__qname__;
182		#elseif (cpp)
183			return untyped e.__ToString();
184		#else
185			var a : Array<String> = untyped e.__ename__;
186			return a.join(".");
187		#end
188	}
189
190	/**
191		Evaluates a class from a name. The class must have been compiled
192		to be accessible.
193	**/
194	public static function resolveClass( name : String ) : Class<Dynamic> untyped {
195		#if php
196			var c = untyped __call__("_hx_qtype", name);
197			if(__php__("$c instanceof _hx_class"))
198				return c;
199			else
200				return null;
201		#elseif cpp
202			return untyped Class.Resolve(name);
203		#else
204			var cl : Class<Dynamic>;
205		#if flash9
206			try {
207				cl = __as__(__global__["flash.utils.getDefinitionByName"](name),Class);
208				if( cl.__isenum )
209					return null;
210				return cl; // skip test below
211			} catch( e : Dynamic ) {
212				switch( name ) {
213				case "Int": return Int;
214				case "Float": return Float;
215				}
216				return null;
217			}
218		#elseif flash
219			cl = __eval__(name);
220		#elseif js
221			try {
222				#if js_namespace
223				if (name.indexOf('.') < 0)
224					cl = eval(js.Boot.__ns + '.' + name);
225				else
226					cl = eval(name);
227				#else
228				cl = eval(name);
229				#end
230			} catch( e : Dynamic ) {
231				cl = null;
232			}
233		#elseif neko
234			var path = name.split(".");
235			cl = Reflect.field(untyped neko.Boot.__classes,path[0]);
236			var i = 1;
237			while( cl != null && i < path.length ) {
238				cl = Reflect.field(cl,path[i]);
239				i += 1;
240			}
241		#else
242			cl = null;
243		#end
244			// ensure that this is a class
245			if( cl == null || cl.__name__ == null )
246				return null;
247			return cl;
248		#end
249	}
250
251
252	/**
253		Evaluates an enum from a name. The enum must have been compiled
254		to be accessible.
255	**/
256	public static function resolveEnum( name : String ) : Enum<Dynamic> untyped {
257		#if php
258			var e = untyped __call__("_hx_qtype", name);
259			if(untyped __php__("$e instanceof _hx_enum"))
260				return e;
261			else
262				return null;
263		#elseif cpp
264			return untyped Class.Resolve(name);
265		#else
266			var e : Dynamic;
267		#if flash9
268			try {
269				e = __global__["flash.utils.getDefinitionByName"](name);
270				if( !e.__isenum )
271					return null;
272				return e;
273			} catch( e : Dynamic ) {
274				if( name == "Bool" ) return Bool;
275				return null;
276			}
277		#elseif flash
278			e = __eval__(name);
279		#elseif js
280			try {
281				#if js_namespace
282				if (name.indexOf('.') < 0)
283					e = eval(js.Boot.__ns + '.' + name);
284				else
285					e = eval(name);
286				#else
287				e = eval(name);
288				#end
289			} catch( err : Dynamic ) {
290				e = null;
291			}
292		#elseif neko
293			var path = name.split(".");
294			e = Reflect.field(neko.Boot.__classes,path[0]);
295			var i = 1;
296			while( e != null && i < path.length ) {
297				e = Reflect.field(e,path[i]);
298				i += 1;
299			}
300		#else
301			e = null;
302		#end
303			// ensure that this is an enum
304			if( e == null || e.__ename__ == null )
305				return null;
306			return e;
307		#end
308	}
309
310	/**
311		Creates an instance of the given class with the list of constructor arguments.
312	**/
313	public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T untyped {
314		#if flash9
315			return switch( args.length ) {
316			case 0: __new__(cl);
317			case 1: __new__(cl,args[0]);
318			case 2: __new__(cl,args[0],args[1]);
319			case 3: __new__(cl,args[0],args[1],args[2]);
320			case 4: __new__(cl,args[0],args[1],args[2],args[3]);
321			case 5: __new__(cl,args[0],args[1],args[2],args[3],args[4]);
322			case 6: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5]);
323			case 7: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
324			case 8: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
325			case 9: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
326			case 10: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
327			case 11: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
328			case 12: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
329			case 13: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
330			case 14: __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
331			default: throw "Too many arguments";
332			}
333		#elseif flash
334			if( cl == Array ) return new Array();
335			var o = { __constructor__ : cl, __proto__ : cl.prototype };
336			cl["apply"](o,args);
337			return o;
338		#elseif neko
339			return __dollar__call(__dollar__objget(cl,__dollar__hash("new".__s)),cl,args.__neko());
340		#elseif js
341			if( args.length <= 3 )
342				return __new__(cl,args[0],args[1],args[2]);
343			if( args.length > 8 )
344				throw "Too many arguments";
345			return __new__(cl,args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
346		#elseif php
347			if(cl.__qname__ == 'Array') return [];
348			if(cl.__qname__ == 'String') return args[0];
349			var c = cl.__rfl__();
350			if(c == null) return null;
351			return __php__("$inst = $c->getConstructor() ? $c->newInstanceArgs($args->a) : $c->newInstanceArgs()");
352		#elseif cpp
353			if (cl!=null)
354				return cl.mConstructArgs(args);
355			return null;
356		#else
357			return null;
358		#end
359	}
360
361	/**
362		Similar to [Reflect.createInstance] excepts that the constructor is not called.
363		This enables you to create an instance without any side-effect.
364	**/
365	public static function createEmptyInstance<T>( cl : Class<T> ) : T untyped {
366		#if flash9
367			try {
368				flash.Boot.skip_constructor = true;
369				var i = __new__(cl);
370				flash.Boot.skip_constructor = false;
371				return i;
372			} catch( e : Dynamic ) {
373				flash.Boot.skip_constructor = false;
374				throw e;
375			}
376			return null;
377		#elseif flash
378			if( cl == Array ) return new Array();
379			var o : Dynamic = __new__(_global["Object"]);
380			o.__proto__ = cl.prototype;
381			return o;
382		#elseif js
383			return __new__(cl,__js__("$_"));
384		#elseif neko
385			var o = __dollar__new(null);
386			__dollar__objsetproto(o,cl.prototype);
387			return o;
388		#elseif php
389			if(cl.__qname__ == 'Array') return [];
390			if(cl.__qname__ == 'String') return '';
391			try {
392				__php__("php_Boot::$skip_constructor = true");
393				var rfl = cl.__rfl__();
394				if(rfl == null) return null;
395				var m = __php__("$rfl->getConstructor()");
396				var nargs : Int = m.getNumberOfRequiredParameters();
397				var i;
398				if(nargs > 0) {
399					var args = __call__("array_fill", 0, m.getNumberOfRequiredParameters(), null);
400					i = __php__("$rfl->newInstanceArgs($args)");
401				} else {
402					i = __php__("$rfl->newInstanceArgs(array())");
403				}
404				__php__("php_Boot::$skip_constructor = false");
405				return i;
406			} catch( e : Dynamic ) {
407				__php__("php_Boot::$skip_constructor = false");
408				throw "Unable to instantiate " + Std.string(cl);
409			}
410			return null;
411		#elseif cpp
412			return cl.mConstructEmpty();
413		#else
414			return null;
415		#end
416	}
417
418	/**
419		Create an instance of an enum by using a constructor name and parameters.
420	**/
421	public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T {
422		#if cpp
423		if (untyped e.mConstructEnum != null)
424			return untyped e.mConstructEnum(constr,params);
425		return null;
426		#else
427		var f = Reflect.field(e,constr);
428		if( f == null ) throw "No such constructor "+constr;
429		if( Reflect.isFunction(f) ) {
430			if( params == null ) throw "Constructor "+constr+" need parameters";
431			return Reflect.callMethod(e,f,params);
432		}
433		if( params != null && params.length != 0 )
434			throw "Constructor "+constr+" does not need parameters";
435		return f;
436		#end
437	}
438
439	/**
440		Create an instance of an enum by using a constructor index and parameters.
441	**/
442	public static function createEnumIndex<T>( e : Enum<T>, index : Int, ?params : Array<Dynamic> ) : T {
443		var c = Type.getEnumConstructs(e)[index];
444		if( c == null ) throw index+" is not a valid enum constructor index";
445		return createEnum(e,c,params);
446	}
447
448	#if flash9
449	static function describe( t : Dynamic, fact : Bool ) untyped {
450		var fields = new Array();
451		var xml : flash.xml.XML = __global__["flash.utils.describeType"](t);
452		if( fact )
453			xml = xml.factory[0];
454		var methods = xml.child("method");
455		for( i in 0...methods.length() )
456			fields.push( Std.string(methods[i].attribute("name")) );
457		var vars = xml.child("variable");
458		for( i in 0...vars.length() )
459			fields.push( Std.string(vars[i].attribute("name")) );
460		return fields;
461	}
462	#end
463
464	/**
465		Returns the list of instance fields.
466	**/
467	public static function getInstanceFields( c : Class<Dynamic> ) : Array<String> {
468		#if flash9
469			return describe(c,true);
470		#elseif php
471			if(untyped c.__qname__ == 'String') return ['substr', 'charAt', 'charCodeAt', 'indexOf', 'lastIndexOf', 'split', 'toLowerCase', 'toUpperCase', 'toString', 'length'];
472			if(untyped c.__qname__ == 'Array') return  ['push', 'concat', 'join', 'pop', 'reverse', 'shift', 'slice', 'sort', 'splice', 'toString', 'copy', 'unshift', 'insert', 'remove', 'iterator', 'length'];
473			untyped __php__("
474			$rfl = $c->__rfl__();
475			if($rfl === null) return new _hx_array(array());
476			$r = array();
477			$internals = array('__construct', '__call', '__get', '__set', '__isset', '__unset', '__toString');
478			$ms = $rfl->getMethods();
479			while(list(, $m) = each($ms)) {
480				$n = $m->getName();
481				if(!$m->isStatic() && ! in_array($n, $internals)) $r[] = $n;
482			}
483			$ps = $rfl->getProperties();
484			while(list(, $p) = each($ps))
485				if(!$p->isStatic()) $r[] = $p->getName()");
486			return untyped __php__("new _hx_array(array_values(array_unique($r)))");
487		#elseif cpp
488			return untyped c.GetInstanceFields();
489		#else
490
491			var a = Reflect.fields(untyped c.prototype);
492			#if js
493				a.remove("__class__");
494			#else
495				c = untyped c.__super__;
496				while( c != null ) {
497					for( f in Reflect.fields(untyped c.prototype) ) {
498						a.remove(f);
499						a.push(f);
500					}
501					c = untyped c.__super__;
502				}
503				a.remove("__class__");
504				#if neko
505				a.remove("__serialize");
506				a.remove("__string");
507				#end
508			#end
509			return a;
510		#end
511	}
512
513	/**
514		Returns the list of a class static fields.
515	**/
516	public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
517		#if flash9
518			var a = describe(c,false);
519			a.remove("__construct__");
520			return a;
521		#elseif php
522			if(untyped c.__qname__ == 'String') return ['fromCharCode'];
523			if(untyped c.__qname__ == 'Array')  return [];
524			untyped __php__("
525			$rfl = $c->__rfl__();
526			if($rfl === null) return new _hx_array(array());
527			$ms = $rfl->getMethods();
528			$r = array();
529			while(list(, $m) = each($ms))
530				if($m->isStatic()) $r[] = $m->getName();
531			$ps = $rfl->getProperties();
532			while(list(, $p) = each($ps))
533				if($p->isStatic()) $r[] = $p->getName();
534			");
535			return untyped __php__("new _hx_array(array_unique($r))");
536		#elseif cpp
537			return untyped c.GetClassFields();
538		#else
539			var a = Reflect.fields(c);
540			a.remove(__unprotect__("__name__"));
541			a.remove(__unprotect__("__interfaces__"));
542			a.remove(__unprotect__("__super__"));
543			#if js
544			a.remove("prototype");
545			#end
546			#if neko
547			a.remove("__string");
548			a.remove("__construct__");
549			a.remove("prototype");
550			a.remove("new");
551			#end
552			return a;
553		#end
554	}
555
556	/**
557		Returns all the available constructor names for an enum.
558	**/
559	public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> untyped {
560		#if php
561			if(__php__("$e->__tname__ == 'Bool'")) return ['true', 'false'];
562			if(__php__("$e->__tname__ == 'Void'")) return [];
563			var rfl = __php__("new ReflectionClass($e->__tname__)");
564			var sps : ArrayAccess<Dynamic> = rfl.getStaticProperties();
565//			var r : ArrayAccess<String> = __call__('array');
566			__php__("$r = array(); while(list($k) = each($sps)) $r[] = $k");
567			sps = rfl.getMethods();
568			__php__("while(list(, $m) = each($sps)) { $n = $m->getName(); if($n != '__construct' && $n != '__toString') $r[] = $n; }");
569			return __php__("new _hx_array($r)");
570		#elseif cpp
571			return untyped e.GetClassFields();
572		#else
573			return untyped e.__constructs__;
574		#end
575	}
576
577	/**
578		Returns the runtime type of a value.
579	**/
580	public static function typeof( v : Dynamic ) : ValueType untyped {
581		#if neko
582			return switch( __dollar__typeof(v) ) {
583			case __dollar__tnull: TNull;
584			case __dollar__tint: TInt;
585			case __dollar__tfloat: TFloat;
586			case __dollar__tbool: TBool;
587			case __dollar__tfunction: TFunction;
588			case __dollar__tobject:
589				var c = v.__class__;
590				if( c != null )
591					TClass(c);
592				else {
593					var e = v.__enum__;
594					if( e != null )
595						TEnum(e);
596					else
597						TObject;
598				}
599			default: TUnknown;
600			}
601		#elseif flash9
602			var cname = __global__["flash.utils.getQualifiedClassName"](v);
603			switch(cname) {
604			case "null": return TNull;
605			case "void": return TNull; // undefined
606			case "int": return TInt;
607			case "Number": return TFloat;
608			case "Boolean": return TBool;
609			case "Object": return TObject;
610			default:
611				var c : Dynamic = null;
612				try {
613					c = __global__["flash.utils.getDefinitionByName"](cname);
614					if( v.hasOwnProperty("prototype") )
615						return TObject;
616					if( c.__isenum )
617						return TEnum(c);
618					return TClass(c);
619				} catch( e : Dynamic ) {
620					if( cname == "builtin.as$0::MethodClosure" || cname.indexOf("-") != -1 )
621						return TFunction;
622					return if( c == null ) TFunction else TClass(c);
623				}
624			}
625			return null;
626		#elseif (flash || js)
627			switch( #if flash __typeof__ #else __js__("typeof") #end(v) ) {
628			#if flash
629			case "null": return TNull;
630			#end
631			case "boolean": return TBool;
632			case "string": return TClass(String);
633			case "number":
634				// this should handle all cases : NaN, +/-Inf and Floats outside range
635				if( Math.ceil(v) == v%2147483648.0 )
636					return TInt;
637				return TFloat;
638			case "object":
639				#if js
640				if( v == null )
641					return TNull;
642				#end
643				var e = v.__enum__;
644				if( e != null )
645					return TEnum(e);
646				var c = v.__class__;
647				if( c != null )
648					return TClass(c);
649				return TObject;
650			case "function":
651				if( v.__name__ != null )
652					return TObject;
653				return TFunction;
654			case "undefined":
655				return TNull;
656			default:
657				return TUnknown;
658			}
659		#elseif php
660			if(v == null) return TNull;
661			if(__call__("is_array", v)) {
662				if(__call__("is_callable", v)) return TFunction;
663				return TClass(Array);
664			}
665			if(__call__("is_string", v)) {
666				if(__call__("_hx_is_lambda", v)) return TFunction;
667				return TClass(String);
668			}
669			if(__call__("is_bool", v)) return TBool;
670			if(__call__("is_int", v)) return TInt;
671			if(__call__("is_float", v)) return TFloat;
672			if(__php__("$v instanceof _hx_anonymous"))  return TObject;
673			if(__php__("$v instanceof _hx_enum"))  return TObject;
674			if(__php__("$v instanceof _hx_class"))  return TObject;
675
676			var c = __php__("_hx_ttype(get_class($v))");
677
678			if(__php__("$c instanceof _hx_enum"))  return TEnum(cast c);
679			if(__php__("$c instanceof _hx_class")) return TClass(cast c);
680			return TUnknown;
681		#elseif cpp
682			if (v==null) return TNull;
683			var t:Int = untyped v.__GetType();
684			switch(t)
685			{
686				case untyped __global__.vtBool : return TBool;
687				case untyped __global__.vtInt : return TInt;
688				case untyped __global__.vtFloat : return TFloat;
689				case untyped __global__.vtFunction : return TFunction;
690				case untyped __global__.vtObject : return TObject;
691				case untyped __global__.vtEnum : return TEnum(v.__GetClass());
692				default:
693					return untyped TClass(v.__GetClass());
694			}
695		#else
696			return TUnknown;
697		#end
698	}
699
700	/**
701		Recursively compare two enums constructors and parameters.
702	**/
703	public static function enumEq<T>( a : T, b : T ) : Bool untyped {
704		if( a == b )
705			return true;
706		#if neko
707			try {
708				if( a.__enum__ == null || a.index != b.index )
709					return false;
710			} catch( e : Dynamic ) {
711				return false;
712			}
713			for( i in 0...__dollar__asize(a.args) )
714				if( !enumEq(a.args[i],b.args[i]) )
715					return false;
716		#elseif flash9
717			try {
718				if( a.index != b.index )
719					return false;
720				var ap : Array<Dynamic> = a.params;
721				var bp : Array<Dynamic> = b.params;
722				for( i in 0...ap.length )
723					if( !enumEq(ap[i],bp[i]) )
724						return false;
725			} catch( e : Dynamic ) {
726				return false;
727			}
728		#elseif php
729			try {
730				if( a.index != b.index )
731					return false;
732				for( i in 0...__call__("count", a.params))
733					if(getEnum(untyped __php__("$a->params[$i]")) != null) {
734						if(!untyped enumEq(__php__("$a->params[$i]"),__php__("$b->params[$i]")))
735							return false;
736					} else {
737						if(!untyped __call__("_hx_equal", __php__("$a->params[$i]"),__php__("$b->params[$i]")))
738							return false;
739					}
740			} catch( e : Dynamic ) {
741				return false;
742			}
743		#elseif cpp
744			return a==b;
745		#elseif flash
746			// no try-catch since no exception possible
747			if( a[0] != b[0] )
748				return false;
749			for( i in 2...a.length )
750				if( !enumEq(a[i],b[i]) )
751					return false;
752			var e = a.__enum__;
753			if( e != b.__enum__ || e == null )
754				return false;
755		#else
756			try {
757				if( a[0] != b[0] )
758					return false;
759				for( i in 2...a.length )
760					if( !enumEq(a[i],b[i]) )
761						return false;
762				var e = a.__enum__;
763				if( e != b.__enum__ || e == null )
764					return false;
765			} catch( e : Dynamic ) {
766				return false;
767			}
768		#end
769		return true;
770	}
771
772	/**
773		Returns the constructor of an enum
774	**/
775	public static function enumConstructor( e : Dynamic ) : String {
776		#if neko
777			return new String(e.tag);
778		#elseif (flash9 || php)
779			return e.tag;
780		#elseif cpp
781			return e.__Tag();
782		#else
783			return e[0];
784		#end
785	}
786
787	/**
788		Returns the parameters of an enum
789	**/
790	public static function enumParameters( e : Dynamic ) : Array<Dynamic> {
791		#if neko
792			return if( e.args == null ) [] else untyped Array.new1(e.args,__dollar__asize(e.args));
793		#elseif flash9
794			return if( e.params == null ) [] else e.params;
795		#elseif cpp
796			return untyped e.__EnumParams();
797		#elseif php
798			if(e.params == null)
799				return [];
800			else
801				return untyped __php__("new _hx_array($e->params)");
802		#else
803			return e.slice(2);
804		#end
805	}
806
807	/**
808		Returns the index of the constructor of an enum
809	**/
810	public inline static function enumIndex( e : Dynamic ) : Int {
811		#if (neko || flash9 || php)
812			return e.index;
813		#elseif cpp
814			return e.__Index();
815		#else
816			return e[1];
817		#end
818	}
819
820}
821