Runtime.hx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. package java.internal;
  2. /**
  3. This class is meant for internal compiler use only. It provides the Haxe runtime
  4. compatibility to the host language. Do not access it directly.
  5. **/
  6. @:native('haxe.lang.Runtime')
  7. @:nativegen
  8. @:classContents('
  9. public static java.lang.Object getField(haxe.lang.IHxObject obj, java.lang.String field, boolean throwErrors)
  10. {
  11. if (obj == null && !throwErrors) return null;
  12. return obj.__hx_getField(field, throwErrors, false, false);
  13. }
  14. public static double getField_f(haxe.lang.IHxObject obj, java.lang.String field, boolean throwErrors)
  15. {
  16. if (obj == null && !throwErrors) return 0.0;
  17. return obj.__hx_getField_f(field, throwErrors, false);
  18. }
  19. public static java.lang.Object setField(haxe.lang.IHxObject obj, java.lang.String field, java.lang.Object value)
  20. {
  21. return obj.__hx_setField(field, value, false);
  22. }
  23. public static double setField_f(haxe.lang.IHxObject obj, java.lang.String field, double value)
  24. {
  25. return obj.__hx_setField_f(field, value, false);
  26. }
  27. public static java.lang.Object callField(haxe.lang.IHxObject obj, java.lang.String field, Array<?> args)
  28. {
  29. return obj.__hx_invokeField(field, args);
  30. }
  31. ')
  32. @:keep class Runtime
  33. {
  34. public static var undefined:Dynamic = { };
  35. @:functionBody('
  36. return new haxe.lang.Closure(obj, field);
  37. ')
  38. public static function closure(obj:Dynamic, field:String):Dynamic
  39. {
  40. return null;
  41. }
  42. @:functionBody('
  43. if (v1 == v2)
  44. return true;
  45. if (v1 == null || v2 == null)
  46. return false;
  47. if (v1 instanceof java.lang.Number)
  48. {
  49. if (!(v2 instanceof java.lang.Number))
  50. return false;
  51. java.lang.Number v1c = (java.lang.Number) v1;
  52. java.lang.Number v2c = (java.lang.Number) v2;
  53. if (v1 instanceof java.lang.Long || v2 instanceof java.lang.Long)
  54. return v1c.longValue() == v2c.longValue();
  55. return v1c.doubleValue() == v2c.doubleValue();
  56. } else if (v1 instanceof java.lang.String || v1 instanceof haxe.lang.IEquatable) { //TODO see what happens with Boolean cases
  57. return v1.equals(v2);
  58. }
  59. return false;
  60. ')
  61. public static function eq(v1:Dynamic, v2:Dynamic):Bool
  62. {
  63. return false;
  64. }
  65. @:functionBody('
  66. if (v1 == v2)
  67. return true;
  68. if (v1 instanceof java.lang.String || v1 instanceof haxe.lang.IEquatable)
  69. {
  70. return v1 != null && v1.equals(v2);
  71. } else {
  72. return v1 == v2;
  73. }
  74. ')
  75. public static function refEq(v1: { }, v2: { } ):Bool
  76. {
  77. return false;
  78. }
  79. @:functionBody('
  80. return v1 == v2 || (v1 != null && v1.equals(v2));
  81. ')
  82. public static function valEq(v1: { }, v2: { } ):Bool
  83. {
  84. return false;
  85. }
  86. @:functionBody('
  87. return (obj == null) ? 0.0 : ((java.lang.Number) obj).doubleValue();
  88. ')
  89. public static function toDouble(obj:Dynamic):Float
  90. {
  91. return 0.0;
  92. }
  93. @:functionBody('
  94. return (obj == null) ? false : ((java.lang.Boolean) obj).booleanValue();
  95. ')
  96. public static function toBool(obj:Dynamic):Bool
  97. {
  98. return false;
  99. }
  100. @:functionBody('
  101. return (obj == null) ? 0 : ((java.lang.Number) obj).intValue();
  102. ')
  103. public static function toInt(obj:Dynamic):Int
  104. {
  105. return 0;
  106. }
  107. @:functionBody('
  108. if (obj != null && obj instanceof java.lang.Number)
  109. {
  110. return true;
  111. } else {
  112. return false;
  113. }
  114. ')
  115. public static function isDouble(obj:Dynamic):Bool
  116. {
  117. return false;
  118. }
  119. @:functionBody('
  120. if (obj != null && obj instanceof java.lang.Number)
  121. {
  122. java.lang.Number n = (java.lang.Number) obj;
  123. return n.doubleValue() == n.intValue();
  124. } else {
  125. return false;
  126. }
  127. ')
  128. public static function isInt(obj:Dynamic):Bool
  129. {
  130. return false;
  131. }
  132. @:functionBody('
  133. java.lang.Class cl = null;
  134. if (o instanceof java.lang.Class)
  135. {
  136. if (o == java.lang.String.class)
  137. return field.equals("fromCharCode");
  138. cl = (java.lang.Class) o;
  139. } else if (o instanceof java.lang.String) {
  140. return haxe.lang.StringRefl.handleGetField( (java.lang.String) o, field, false) != null;
  141. } else {
  142. cl = o.getClass();
  143. }
  144. try
  145. {
  146. java.lang.reflect.Field f = cl.getField(field);
  147. return true;
  148. }
  149. catch(Throwable t)
  150. {
  151. java.lang.reflect.Method[] ms = cl.getMethods();
  152. for (int i = 0; i < ms.length; i++)
  153. {
  154. if (ms[i].getName().equals(field))
  155. {
  156. return true;
  157. }
  158. }
  159. }
  160. return false;
  161. ')
  162. public static function slowHasField(o:Dynamic, field:String):Bool
  163. {
  164. return false;
  165. }
  166. @:functionBody('
  167. if (v1 == v2)
  168. return 0;
  169. if (v1 instanceof java.lang.Number)
  170. {
  171. java.lang.Number v1c = (java.lang.Number) v1;
  172. java.lang.Number v2c = (java.lang.Number) v2;
  173. if (v1 instanceof java.lang.Long || v2 instanceof java.lang.Long)
  174. {
  175. long l1 = (v1 == null) ? 0L : v1c.longValue();
  176. long l2 = (v2 == null) ? 0L : v2c.longValue();
  177. return (int) (l1 - l2);
  178. } else {
  179. double d1 = (v1 == null) ? 0.0 : v1c.doubleValue();
  180. double d2 = (v2 == null) ? 0.0 : v2c.doubleValue();
  181. return (int) (d1 - d2);
  182. }
  183. }
  184. //if it\'s not a number it must be a String
  185. return ((java.lang.String) v1).compareTo((java.lang.String) v2);
  186. ')
  187. public static function compare(v1:Dynamic, v2:Dynamic):Int
  188. {
  189. return 0;
  190. }
  191. @:functionBody('
  192. if (v1 instanceof java.lang.String || v2 instanceof java.lang.String)
  193. return (v1 + "") + (v2 + "");
  194. if (v1 instanceof java.lang.Number || v2 instanceof java.lang.Number)
  195. {
  196. java.lang.Number v1c = (java.lang.Number) v1;
  197. java.lang.Number v2c = (java.lang.Number) v2;
  198. double d1 = (v1 == null) ? 0.0 : v1c.doubleValue();
  199. double d2 = (v2 == null) ? 0.0 : v2c.doubleValue();
  200. return d1 + d2;
  201. }
  202. throw new java.lang.IllegalArgumentException("Cannot dynamically add " + v1 + " and " + v2);
  203. ')
  204. public static function plus(v1:Dynamic, v2:Dynamic):Dynamic
  205. {
  206. return null;
  207. }
  208. @:functionBody('
  209. if (obj == null)
  210. if (throwErrors)
  211. throw new java.lang.NullPointerException("Cannot access field \'" + field + "\' of null.");
  212. else
  213. return null;
  214. java.lang.Class cl = null;
  215. try
  216. {
  217. if (obj instanceof java.lang.Class)
  218. {
  219. if (obj == java.lang.String.class && field.equals("fromCharCode"))
  220. return new haxe.lang.Closure(haxe.lang.StringExt.class, field);
  221. cl = (java.lang.Class) obj;
  222. obj = null;
  223. } else if (obj instanceof java.lang.String) {
  224. return haxe.lang.StringRefl.handleGetField((java.lang.String) obj, field, throwErrors);
  225. } else {
  226. cl = obj.getClass();
  227. }
  228. java.lang.reflect.Field f = cl.getField(field);
  229. f.setAccessible(true);
  230. return f.get(obj);
  231. } catch (Throwable t)
  232. {
  233. try
  234. {
  235. java.lang.reflect.Method[] ms = cl.getMethods();
  236. for (int i = 0; i < ms.length; i++)
  237. {
  238. if (ms[i].getName().equals(field))
  239. {
  240. return new haxe.lang.Closure(obj != null ? obj : cl, field);
  241. }
  242. }
  243. } catch (Throwable t2)
  244. {
  245. }
  246. if (throwErrors)
  247. throw HaxeException.wrap(t);
  248. return null;
  249. }
  250. ')
  251. public static function slowGetField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic
  252. {
  253. return null;
  254. }
  255. @:functionBody('
  256. java.lang.Class cl = null;
  257. if (obj instanceof java.lang.Class)
  258. {
  259. cl = (java.lang.Class) obj;
  260. obj = null;
  261. } else {
  262. cl = obj.getClass();
  263. }
  264. try {
  265. java.lang.reflect.Field f = cl.getField(field);
  266. f.setAccessible(true);
  267. //FIXME we must evaluate if field to be set receives either int or double
  268. if (isInt(value))
  269. {
  270. f.setInt(obj, toInt(value));
  271. } else if (isDouble(value)) {
  272. f.setDouble(obj, toDouble(value));
  273. } else {
  274. f.set(obj, value);
  275. }
  276. return value;
  277. }
  278. catch (Throwable t)
  279. {
  280. throw HaxeException.wrap(t);
  281. }
  282. ')
  283. public static function slowSetField(obj:Dynamic, field:String, value:Dynamic):Dynamic
  284. {
  285. return null;
  286. }
  287. @:functionBody('
  288. java.lang.Class cl = null;
  289. if (obj instanceof java.lang.Class)
  290. {
  291. if (obj == java.lang.String.class && field.equals("fromCharCode"))
  292. return haxe.lang.StringExt.fromCharCode(toInt(args.__get(0)));
  293. cl = (java.lang.Class) obj;
  294. obj = null;
  295. } else if (obj instanceof java.lang.String) {
  296. return haxe.lang.StringRefl.handleCallField((java.lang.String) obj, field, args);
  297. } else {
  298. cl = obj.getClass();
  299. }
  300. if (args == null) args = new Array();
  301. int len = args.length;
  302. java.lang.Class[] cls = new java.lang.Class[len];
  303. java.lang.Object[] objs = new java.lang.Object[len];
  304. java.lang.reflect.Method[] ms = cl.getDeclaredMethods();
  305. int msl = ms.length;
  306. int realMsl = 0;
  307. for(int i =0; i < msl; i++)
  308. {
  309. if (ms[i].getName() != field || (!ms[i].isVarArgs() && ms[i].getParameterTypes().length != len))
  310. {
  311. ms[i] = null;
  312. } else {
  313. ms[realMsl] = ms[i];
  314. if (realMsl != i)
  315. ms[i] = null;
  316. realMsl++;
  317. }
  318. }
  319. boolean hasNumber = false;
  320. for (int i = 0; i < len; i++)
  321. {
  322. Object o = args.__get(i);
  323. objs[i]= o;
  324. cls[i] = o.getClass();
  325. if (!(o instanceof java.lang.Number))
  326. {
  327. msl = realMsl;
  328. realMsl = 0;
  329. for (int j = 0; j < msl; j++)
  330. {
  331. java.lang.Class[] allcls = ms[j].getParameterTypes();
  332. if (i < allcls.length)
  333. {
  334. if (!allcls[i].isAssignableFrom(cls[i]))
  335. {
  336. ms[j] = null;
  337. } else {
  338. ms[realMsl] = ms[j];
  339. if (realMsl != j)
  340. ms[j] = null;
  341. realMsl++;
  342. }
  343. }
  344. }
  345. } else {
  346. hasNumber = true;
  347. }
  348. }
  349. java.lang.reflect.Method found;
  350. if (ms.length == 0 || (found = ms[0]) == null)
  351. throw haxe.lang.HaxeException.wrap("No compatible method found for: " + field);
  352. if (hasNumber)
  353. {
  354. java.lang.Class[] allcls = found.getParameterTypes();
  355. for (int i = 0; i < len; i++)
  356. {
  357. java.lang.Object o = objs[i];
  358. if (o instanceof java.lang.Number)
  359. {
  360. java.lang.Class curCls = null;
  361. if (i < allcls.length)
  362. {
  363. curCls = allcls[i];
  364. if (!curCls.isAssignableFrom(o.getClass()))
  365. {
  366. String name = curCls.getName();
  367. if (name.equals("double") || name.equals("java.lang.Double"))
  368. {
  369. objs[i] = ((java.lang.Number)o).doubleValue();
  370. } else if (name.equals("int") || name.equals("java.lang.Integer"))
  371. {
  372. objs[i] = ((java.lang.Number)o).intValue();
  373. } else if (name.equals("float") || name.equals("java.lang.Float"))
  374. {
  375. objs[i] = ((java.lang.Number)o).floatValue();
  376. } else if (name.equals("byte") || name.equals("java.lang.Byte"))
  377. {
  378. objs[i] = ((java.lang.Number)o).byteValue();
  379. } else if (name.equals("short") || name.equals("java.lang.Short"))
  380. {
  381. objs[i] = ((java.lang.Number)o).shortValue();
  382. }
  383. }
  384. } //else varargs not handled TODO
  385. }
  386. }
  387. }
  388. try {
  389. found.setAccessible(true);
  390. return found.invoke(obj, objs);
  391. }
  392. catch (java.lang.reflect.InvocationTargetException e)
  393. {
  394. throw haxe.lang.HaxeException.wrap(e.getCause());
  395. }
  396. catch (Throwable t)
  397. {
  398. throw haxe.lang.HaxeException.wrap(t);
  399. }
  400. ')
  401. public static function slowCallField(obj:Dynamic, field:String, args:Array<Dynamic>):Dynamic
  402. {
  403. return null;
  404. }
  405. @:functionBody('
  406. if (obj instanceof haxe.lang.IHxObject)
  407. {
  408. return ((haxe.lang.IHxObject) obj).__hx_invokeField(field, args);
  409. }
  410. return slowCallField(obj, field, args);
  411. ')
  412. public static function callField(obj:Dynamic, field:String, args:Array<Dynamic>):Dynamic
  413. {
  414. return null;
  415. }
  416. @:functionBody('
  417. if (obj instanceof haxe.lang.IHxObject)
  418. return ((haxe.lang.IHxObject) obj).__hx_getField(field, throwErrors, false, false);
  419. return slowGetField(obj, field, throwErrors);
  420. ')
  421. public static function getField(obj:Dynamic, field:String, throwErrors:Bool):Dynamic
  422. {
  423. return null;
  424. }
  425. @:functionBody('
  426. if (obj instanceof haxe.lang.IHxObject)
  427. return ((haxe.lang.IHxObject) obj).__hx_getField_f(field, throwErrors, false);
  428. return toDouble(slowGetField(obj, field, throwErrors));
  429. ')
  430. public static function getField_f(obj:Dynamic, field:String, throwErrors:Bool):Float
  431. {
  432. return 0.0;
  433. }
  434. @:functionBody('
  435. if (obj instanceof haxe.lang.IHxObject)
  436. return ((haxe.lang.IHxObject) obj).__hx_setField(field, value, false);
  437. return slowSetField(obj, field, value);
  438. ')
  439. public static function setField(obj:Dynamic, field:String, value:Dynamic):Dynamic
  440. {
  441. return null;
  442. }
  443. @:functionBody('
  444. if (obj instanceof haxe.lang.IHxObject)
  445. return ((haxe.lang.IHxObject) obj).__hx_setField_f(field, value, false);
  446. return toDouble(slowSetField(obj, field, value));
  447. ')
  448. public static function setField_f(obj:Dynamic, field:String, value:Float):Float
  449. {
  450. return 0.0;
  451. }
  452. public static function toString(obj:Dynamic):String
  453. {
  454. if (obj == null)
  455. return null;
  456. return untyped obj.toString();
  457. }
  458. }
  459. @:native("haxe.lang.EmptyObject") private enum EmptyObject
  460. {
  461. EMPTY;
  462. }