Runtime.hx 12 KB

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