PageRenderTime 80ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/std/php/_std/Type.hx

https://gitlab.com/ezeql/haxe
Haxe | 266 lines | 219 code | 26 blank | 21 comment | 84 complexity | 3fb63eb69872970a3bcc060c15387589 MD5 | raw file
  1. /*
  2. * Copyright (C)2005-2012 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. enum ValueType {
  23. TNull;
  24. TInt;
  25. TFloat;
  26. TBool;
  27. TObject;
  28. TFunction;
  29. TClass( c : Class<Dynamic> );
  30. TEnum( e : Enum<Dynamic> );
  31. TUnknown;
  32. }
  33. @:coreApi class Type {
  34. public static function getClass<T>( o : T ) : Class<T> untyped {
  35. if(o == null) return null;
  36. untyped if(__call__("is_array", o)) {
  37. if(__call__("count", o) == 2 && __call__("is_callable", o)) return null;
  38. return __call__("_hx_ttype", 'Array');
  39. }
  40. if(untyped __call__("is_string", o)) {
  41. if(__call__("_hx_is_lambda", untyped o)) return null;
  42. return __call__("_hx_ttype", 'String');
  43. }
  44. if(!untyped __call__("is_object", o)) {
  45. return null;
  46. }
  47. var c = __call__("get_class", o);
  48. if(c == false || c == '_hx_anonymous' || __call__("is_subclass_of", c, "enum"))
  49. return null;
  50. else
  51. return __call__("_hx_ttype", c);
  52. }
  53. public static function getEnum( o : EnumValue ) : Enum<Dynamic> untyped {
  54. if(!__php__("$o instanceof Enum"))
  55. return null;
  56. else
  57. return __php__("_hx_ttype(get_class($o))");
  58. }
  59. public static function getSuperClass( c : Class<Dynamic> ) : Class<Dynamic> {
  60. var s = untyped __call__("get_parent_class", c.__tname__);
  61. if(s == false)
  62. return null;
  63. else
  64. return untyped __call__("_hx_ttype", s);
  65. }
  66. public static function getClassName( c : Class<Dynamic> ) : String {
  67. if( c == null )
  68. return null;
  69. return untyped c.__qname__;
  70. }
  71. public static function getEnumName( e : Enum<Dynamic> ) : String {
  72. return untyped e.__qname__;
  73. }
  74. public static function resolveClass( name : String ) : Class<Dynamic> untyped {
  75. var c = untyped __call__("_hx_qtype", name);
  76. if(__php__("$c instanceof _hx_class || $c instanceof _hx_interface"))
  77. return c;
  78. else
  79. return null;
  80. }
  81. public static function resolveEnum( name : String ) : Enum<Dynamic> {
  82. var e = untyped __call__("_hx_qtype", name);
  83. if(untyped __php__("$e instanceof _hx_enum"))
  84. return e;
  85. else
  86. return null;
  87. }
  88. public static function createInstance<T>( cl : Class<T>, args : Array<Dynamic> ) : T untyped {
  89. if(cl.__qname__ == 'Array') return [];
  90. if(cl.__qname__ == 'String') return args[0];
  91. var c = cl.__rfl__();
  92. if(c == null) return null;
  93. return __php__("$inst = $c->getConstructor() ? $c->newInstanceArgs($args->a) : $c->newInstanceArgs()");
  94. }
  95. public static function createEmptyInstance<T>( cl : Class<T> ) : T untyped {
  96. if(cl.__qname__ == 'Array') return [];
  97. if(cl.__qname__ == 'String') return '';
  98. try {
  99. __php__("php_Boot::$skip_constructor = true");
  100. var rfl = cl.__rfl__();
  101. if(rfl == null) return null;
  102. var m = __php__("$rfl->getConstructor()");
  103. var nargs : Int = m.getNumberOfRequiredParameters();
  104. var i;
  105. if(nargs > 0) {
  106. var args = __call__("array_fill", 0, m.getNumberOfRequiredParameters(), null);
  107. i = __php__("$rfl->newInstanceArgs($args)");
  108. } else {
  109. i = __php__("$rfl->newInstanceArgs(array())");
  110. }
  111. __php__("php_Boot::$skip_constructor = false");
  112. return i;
  113. } catch( e : Dynamic ) {
  114. __php__("php_Boot::$skip_constructor = false");
  115. throw "Unable to instantiate " + Std.string(cl);
  116. }
  117. return null;
  118. }
  119. public static function createEnum<T>( e : Enum<T>, constr : String, ?params : Array<Dynamic> ) : T {
  120. var f:Dynamic = Reflect.field(e,constr);
  121. if( f == null ) throw "No such constructor "+constr;
  122. if( Reflect.isFunction(f) ) {
  123. if( params == null ) throw "Constructor "+constr+" need parameters";
  124. return Reflect.callMethod(e,f,params);
  125. }
  126. if( params != null && params.length != 0 )
  127. throw "Constructor "+constr+" does not need parameters";
  128. return f;
  129. }
  130. public static function createEnumIndex<T>( e : Enum<T>, index : Int, ?params : Array<Dynamic> ) : T {
  131. var c = Type.getEnumConstructs(e)[index];
  132. if( c == null ) throw index+" is not a valid enum constructor index";
  133. return createEnum(e,c,params);
  134. }
  135. public static function getInstanceFields( c : Class<Dynamic> ) : Array<String> {
  136. if(untyped c.__qname__ == 'String') return ['substr', 'charAt', 'charCodeAt', 'indexOf', 'lastIndexOf', 'split', 'toLowerCase', 'toUpperCase', 'toString', 'length'];
  137. if(untyped c.__qname__ == 'Array') return ['push', 'concat', 'join', 'pop', 'reverse', 'shift', 'slice', 'sort', 'splice', 'toString', 'copy', 'unshift', 'insert', 'remove', 'iterator', 'length'];
  138. untyped __php__("
  139. $rfl = $c->__rfl__();
  140. if($rfl === null) return new _hx_array(array());
  141. $r = array();
  142. $internals = array('__construct', '__call', '__get', '__set', '__isset', '__unset', '__toString');
  143. $ms = $rfl->getMethods();
  144. while(list(, $m) = each($ms)) {
  145. $n = $m->getName();
  146. if(!$m->isStatic() && !in_array($n, $internals)) $r[] = $n;
  147. }
  148. $ps = $rfl->getProperties();
  149. while(list(, $p) = each($ps))
  150. if(!$p->isStatic() && ($name = $p->getName()) !== '__dynamics') $r[] = $name;
  151. ");
  152. return untyped __php__("new _hx_array(array_values(array_unique($r)))");
  153. }
  154. public static function getClassFields( c : Class<Dynamic> ) : Array<String> {
  155. if(untyped c.__qname__ == 'String') return ['fromCharCode'];
  156. if(untyped c.__qname__ == 'Array') return [];
  157. untyped __php__("
  158. $rfl = $c->__rfl__();
  159. if($rfl === null) return new _hx_array(array());
  160. $ms = $rfl->getMethods(ReflectionMethod::IS_STATIC);
  161. $r = array();
  162. while(list(, $m) = each($ms)) {
  163. $cls = $m->getDeclaringClass();
  164. if($cls->getName() == $c->__tname__) $r[] = $m->getName();
  165. }
  166. $ps = $rfl->getProperties(ReflectionMethod::IS_STATIC);
  167. while(list(, $p) = each($ps)) {
  168. $cls = $p->getDeclaringClass();
  169. if($cls->getName() == $c->__tname__ && ($name = $p->getName()) !== '__properties__') $r[] = $name;
  170. }
  171. ");
  172. return untyped __php__("new _hx_array(array_unique($r))");
  173. }
  174. public static function getEnumConstructs( e : Enum<Dynamic> ) : Array<String> untyped {
  175. if (__php__("$e->__tname__ == 'Bool'")) return ['true', 'false'];
  176. if (__php__("$e->__tname__ == 'Void'")) return [];
  177. return __call__("new _hx_array", e.__constructors);
  178. }
  179. public static function typeof( v : Dynamic ) : ValueType untyped {
  180. if(v == null) return TNull;
  181. if(__call__("is_array", v)) {
  182. if(__call__("is_callable", v)) return TFunction;
  183. return TClass(Array);
  184. }
  185. if(__call__("is_string", v)) {
  186. if(__call__("_hx_is_lambda", v)) return TFunction;
  187. return TClass(String);
  188. }
  189. if(__call__("is_bool", v)) return TBool;
  190. if(__call__("is_int", v)) return TInt;
  191. if(__call__("is_float", v)) return TFloat;
  192. if(__php__("$v instanceof _hx_anonymous")) return TObject;
  193. if(__php__("$v instanceof _hx_enum")) return TObject;
  194. if(__php__("$v instanceof _hx_class")) return TObject;
  195. var c = __php__("_hx_ttype(get_class($v))");
  196. if(__php__("$c instanceof _hx_enum")) return TEnum(cast c);
  197. if(__php__("$c instanceof _hx_class")) return TClass(cast c);
  198. return TUnknown;
  199. }
  200. public static function enumEq<T>( a : T, b : T ) : Bool untyped {
  201. if( a == b )
  202. return true;
  203. try {
  204. if( a.index != b.index )
  205. return false;
  206. for( i in 0...__call__("count", a.params))
  207. if(getEnum(untyped __php__("$a->params[$i]")) != null) {
  208. if(!untyped enumEq(__php__("$a->params[$i]"),__php__("$b->params[$i]")))
  209. return false;
  210. } else {
  211. if(!untyped __call__("_hx_equal", __php__("$a->params[$i]"),__php__("$b->params[$i]")))
  212. return false;
  213. }
  214. } catch( e : Dynamic ) {
  215. return false;
  216. }
  217. return true;
  218. }
  219. public static function enumConstructor( e : EnumValue ) : String {
  220. return untyped e.tag;
  221. }
  222. public static function enumParameters( e : EnumValue ) : Array<Dynamic> untyped {
  223. if(e.params == null)
  224. return [];
  225. else
  226. return __php__("new _hx_array($e->params)");
  227. }
  228. public inline static function enumIndex( e : EnumValue ) : Int {
  229. return untyped e.index;
  230. }
  231. public static function allEnums<T>( e : Enum<T> ) : Array<T> {
  232. var all = [];
  233. for( c in getEnumConstructs(e) ) {
  234. var v = Reflect.field(e,c);
  235. if( !Reflect.isFunction(v) )
  236. all.push(v);
  237. }
  238. return all;
  239. }
  240. }