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