Boot.hx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. package python;
  2. import python.internal.ArrayImpl;
  3. import python.internal.StringImpl;
  4. import python.internal.EnumImpl;
  5. import python.internal.HxOverrides;
  6. import python.internal.HxException;
  7. import python.internal.AnonObject;
  8. import python.Syntax;
  9. private extern class Set <T>
  10. {
  11. public inline function has (v:T):Bool
  12. {
  13. return python.Syntax.isIn(v, this);
  14. }
  15. }
  16. @:preCode("
  17. import builtins as _hx_builtin
  18. _hx_classes = dict()
  19. class _hx_AnonObject(object):
  20. def __init__(self, fields):
  21. self.__dict__ = fields
  22. _hx_c = _hx_AnonObject({})
  23. _hx_c._hx_AnonObject = _hx_AnonObject
  24. import functools as _hx_functools
  25. import math as _hx_math
  26. ")
  27. @:keep class Boot {
  28. @:keep static function __init__ () {
  29. Syntax.importAs("inspect", "_hx_boot_inspect");
  30. Boot.inspect = Syntax.untypedPython("_hx_boot_inspect");
  31. Boot.builtin = Syntax.untypedPython("_hx_builtin");
  32. }
  33. static function mkSet <T>(a:Array<T>):Set<T> return Syntax.callField(builtin, "set", a);
  34. static var keywords:Set<String> = mkSet(
  35. [
  36. "and", "del", "from", "not", "while",
  37. "as", "elif", "global", "or", "with",
  38. "assert", "else", "if", "pass", "yield",
  39. "break", "except", "import", "print", "float",
  40. "class", "exec", "in", "raise",
  41. "continue", "finally", "is", "return",
  42. "def", "for", "lambda", "try",
  43. "None", "list"
  44. ]);
  45. static function arrayJoin <T>(x:Array<T>, sep:String):String {
  46. return Syntax.field(sep, "join")(x.map(python.Boot.toString));
  47. }
  48. static function isInstance(o:Dynamic, x:Dynamic):Bool {
  49. return Syntax.callField(builtin, "isinstance", o, x);
  50. }
  51. static function builtinStr(o:Dynamic):String {
  52. return Syntax.callField(builtin, "str", o);
  53. }
  54. static function builtinHasAttr(o:Dynamic, x:String):Bool {
  55. return Syntax.callField(builtin, "hasattr", o, x);
  56. }
  57. static function builtinGetAttr(o:Dynamic, x:String):Dynamic {
  58. return Syntax.callField(builtin, "getattr", o, x);
  59. }
  60. static function isPyBool(o:Dynamic):Bool {
  61. return isInstance(o, Syntax.field(builtin, "bool"));
  62. }
  63. static function isPyInt(o:Dynamic):Bool {
  64. return isInstance(o, Syntax.field(builtin, "int"));
  65. }
  66. static function isPyFloat(o:Dynamic):Bool {
  67. return isInstance(o, Syntax.field(builtin, "float"));
  68. }
  69. static function builtinLen(o:Dynamic):Int {
  70. return Syntax.callField(builtin, "len", o);
  71. }
  72. static function builtinInt(o:Dynamic):Int {
  73. return Syntax.callField(builtin, "int", o);
  74. }
  75. static function builtinCallable(o:Dynamic):Bool {
  76. return Syntax.callField(builtin, "callable", o);
  77. }
  78. static function inspectGetMembers(o:Dynamic, f:String->Bool):Void {
  79. return Syntax.callField(inspect, "getmembers", o, f);
  80. }
  81. static function inspectIsClass(o:Dynamic):Bool {
  82. return Syntax.callField(inspect, "isclass", o);
  83. }
  84. static function inspectIsFunction(o:Dynamic):Bool {
  85. return Syntax.callField(inspect, "isclass", o);
  86. }
  87. static function inspectIsMethod(o:Dynamic):Bool {
  88. return Syntax.callField(inspect, "isclass", o);
  89. }
  90. static var builtin:Dynamic;
  91. static var inspect:Dynamic;
  92. @:keep static inline function isClass(o:Dynamic) : Bool {
  93. return o != null && (o == String || inspectIsClass(o));
  94. //return untyped __define_feature__("python.Boot.isClass", o._hx_class);
  95. }
  96. @:keep static function isAnonObject (o:Dynamic) {
  97. return isInstance(o, AnonObject);
  98. }
  99. @:keep private static function _add_dynamic(a:Dynamic,b:Dynamic):Dynamic
  100. {
  101. if (isInstance(a, String) || isInstance(b, String)) {
  102. return toString1(a,"") + toString1(b,"");
  103. }
  104. return Syntax.binop(a, "+", b);
  105. }
  106. @:keep static function toString (o:Dynamic) {
  107. return toString1(o, "");
  108. }
  109. @:keep private static function toString1(o:Dynamic,s:String):String {
  110. if (s == null) s = "";
  111. if( o == null ) return "null";
  112. if( s.length >= 5 ) return "<...>"; // too much deep recursion
  113. if (isInstance(o, String)) return o;
  114. if (isPyBool(o)) {
  115. if ((o:Bool)) return "true" else return "false";
  116. }
  117. if (isPyInt(o)) {
  118. return builtinStr(o);
  119. }
  120. // 1.0 should be printed as 1
  121. if (isPyFloat(o)) {
  122. try {
  123. if (o == builtinInt(o)) {
  124. return builtinStr(Math.round(o));
  125. } else {
  126. return builtinStr(o);
  127. }
  128. } catch (e:Dynamic) {
  129. return builtinStr(o);
  130. }
  131. }
  132. if (inspectIsFunction(o) || inspectIsMethod(o)) return "<function>";
  133. if (isInstance(o, Array))
  134. {
  135. var o1:Array<Dynamic> = o;
  136. var l = o1.length;
  137. var st = "[";
  138. s += "\t";
  139. for( i in 0...l ) {
  140. var prefix = "";
  141. if (i > 0) {
  142. prefix = ",";
  143. }
  144. st += prefix + toString1(o1[i],s);
  145. }
  146. st += "]";
  147. return st;
  148. }
  149. try {
  150. if (builtinHasAttr(o, "toString")) {
  151. return o.toString();
  152. }
  153. } catch (e:Dynamic) {
  154. }
  155. if (builtinHasAttr(o, "__class__"))
  156. {
  157. if (isInstance(o, AnonObject))
  158. {
  159. var toStr = null;
  160. try
  161. {
  162. var fields = fields(o);
  163. var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
  164. toStr = "{ " + arrayJoin(fieldsStr, ", ") + " }";
  165. }
  166. catch (e:Dynamic) {
  167. return "{ ... }";
  168. }
  169. if (toStr == null)
  170. {
  171. return "{ ... }";
  172. }
  173. else
  174. {
  175. return toStr;
  176. }
  177. }
  178. if (isInstance(o, Enum)) {
  179. var l = builtinLen(o.params);
  180. var hasParams = l > 0;
  181. if (hasParams) {
  182. var paramsStr = "";
  183. for (i in 0...l) {
  184. var prefix = "";
  185. if (i > 0) {
  186. prefix = ",";
  187. }
  188. paramsStr += prefix + toString1(o.params[i],s);
  189. }
  190. return o.tag + "(" + paramsStr + ")";
  191. } else {
  192. return o.tag;
  193. }
  194. }
  195. if (builtinHasAttr(o, "_hx_class_name") && Syntax.field(Syntax.field(o, "__class__"), "__name__") != "type") {
  196. var fields = getInstanceFields(o);
  197. var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
  198. var toStr = o._hx_class_name + "( " + arrayJoin(fieldsStr, ", ") + " )";
  199. return toStr;
  200. }
  201. if (builtinHasAttr(o, "_hx_class_name") && Syntax.field(Syntax.field(o, "__class__"), "__name__") == "type") {
  202. var fields = getClassFields(o);
  203. var fieldsStr = [for (f in fields) '$f : ${toString1(field(o,f), s+"\t")}'];
  204. var toStr = "#" + o._hx_class_name + "( " + arrayJoin(fieldsStr, ", ") + " )";
  205. return toStr;
  206. }
  207. if (o == String) {
  208. return "#String";
  209. }
  210. //if (builtinHasAttr(o, "_hx_name")) {
  211. // return "#" + untyped o._hx_name;
  212. //}
  213. if (o == Array) {
  214. return "#Array";
  215. }
  216. if (builtinCallable(o)) {
  217. return "function";
  218. }
  219. try {
  220. if (builtinHasAttr(o, "__repr__")) {
  221. return Syntax.callField(o, "__repr__");
  222. }
  223. } catch (e:Dynamic) {}
  224. if (builtinHasAttr(o, "__str__")) {
  225. return Syntax.callField(o, "__str__", []);
  226. }
  227. if (builtinHasAttr(o, "__name__")) {
  228. return Syntax.field(o, "__name__");
  229. }
  230. return "???";
  231. } else {
  232. try {
  233. inspectGetMembers(o, function (_) return true);
  234. return builtinStr(o);
  235. } catch (e:Dynamic) {
  236. return "???";
  237. }
  238. }
  239. }
  240. static function fields (o:Dynamic) {
  241. var a = [];
  242. if (o != null)
  243. {
  244. if (builtinHasAttr(o, "_hx_fields"))
  245. {
  246. var fields:Array<String> = Syntax.field(o, "_hx_fields");
  247. return fields.copy();
  248. }
  249. if (isInstance(o, AnonObject))
  250. {
  251. var d:Dynamic = Syntax.field(o, "__dict__");
  252. var keys = d.keys();
  253. var handler = unhandleKeywords;
  254. Syntax.untypedPython("for k in keys:");
  255. Syntax.untypedPython(" a.append(handler(k))");
  256. }
  257. else if (builtinHasAttr(o, "__dict__"))
  258. {
  259. var a = [];
  260. var d:Dynamic = Syntax.field(o, "__dict__");
  261. var keys = d.keys();
  262. Syntax.untypedPython("for k in keys:");
  263. Syntax.untypedPython(" a.append(k)");
  264. }
  265. }
  266. return a;
  267. }
  268. static inline function isString (o:Dynamic):Bool {
  269. return isInstance(o, String);
  270. }
  271. static inline function isArray (o:Dynamic):Bool {
  272. return isInstance(o, Array);
  273. }
  274. @:keep static function field( o : Dynamic, field : String ) : Dynamic
  275. {
  276. if (field == null) return null;
  277. switch (field) {
  278. case "length" if (isString(o)): return StringImpl.get_length(o);
  279. case "length" if (isArray(o)): return ArrayImpl.get_length(o);
  280. case "toLowerCase" if (isString(o)): return StringImpl.toLowerCase.bind(o);
  281. case "toUpperCase" if (isString(o)): return StringImpl.toUpperCase.bind(o);
  282. case "charAt" if (isString(o)): return StringImpl.charAt.bind(o);
  283. case "charCodeAt" if (isString(o)): return StringImpl.charCodeAt.bind(o);
  284. case "indexOf" if (isString(o)): return StringImpl.indexOf.bind(o);
  285. case "lastIndexOf" if (isString(o)): return StringImpl.lastIndexOf.bind(o);
  286. case "split" if (isString(o)): return StringImpl.split.bind(o);
  287. case "substr" if (isString(o)): return StringImpl.substr.bind(o);
  288. case "substring" if (isString(o)): return StringImpl.substring.bind(o);
  289. case "toString" if (isString(o)): return StringImpl.toString.bind(o);
  290. case "map" if (isArray(o)): return ArrayImpl.map.bind(o);
  291. case "filter" if (isArray(o)): return ArrayImpl.filter.bind(o);
  292. case "concat" if (isArray(o)): return ArrayImpl.concat.bind(o);
  293. case "copy" if (isArray(o)): return function () return ArrayImpl.copy(o);
  294. case "iterator" if (isArray(o)): return ArrayImpl.iterator.bind(o);
  295. case "insert" if (isArray(o)): return ArrayImpl.insert.bind(o);
  296. case "join" if (isArray(o)): return function (sep) return ArrayImpl.join(o, sep);
  297. case "toString" if (isArray(o)): return ArrayImpl.toString.bind(o);
  298. case "pop" if (isArray(o)): return ArrayImpl.pop.bind(o);
  299. case "push" if (isArray(o)): return ArrayImpl.push.bind(o);
  300. case "unshift" if (isArray(o)): return ArrayImpl.unshift.bind(o);
  301. case "indexOf" if (isArray(o)): return ArrayImpl.indexOf.bind(o);
  302. case "lastIndexOf" if (isArray(o)): return ArrayImpl.lastIndexOf.bind(o);
  303. case "remove" if (isArray(o)): return ArrayImpl.remove.bind(o);
  304. case "reverse" if (isArray(o)): return ArrayImpl.reverse.bind(o);
  305. case "shift" if (isArray(o)): return ArrayImpl.shift.bind(o);
  306. case "slice" if (isArray(o)): return ArrayImpl.slice.bind(o);
  307. case "sort" if (isArray(o)): return ArrayImpl.sort.bind(o);
  308. case "splice" if (isArray(o)): return ArrayImpl.splice.bind(o);
  309. }
  310. var field = handleKeywords(field);
  311. return if (builtinHasAttr(o, field)) builtinGetAttr(o, field) else null;
  312. }
  313. static function getInstanceFields( c : Class<Dynamic> ) : Array<String> {
  314. var f = if (builtinHasAttr(c, "_hx_fields")) {
  315. var x:Array<String> = Syntax.field(c, "_hx_fields");
  316. var x2:Array<String> = Syntax.field(c, "_hx_methods");
  317. x.concat(x2);
  318. } else {
  319. [];
  320. }
  321. var sc = getSuperClass(c);
  322. if (sc == null) {
  323. return f;
  324. } else {
  325. var scArr = getInstanceFields(sc);
  326. var scMap = [for (f in scArr) f => f];
  327. var res = [];
  328. for (f1 in f) {
  329. if (!scMap.exists(f1)) {
  330. scArr.push(f1);
  331. }
  332. }
  333. return scArr;
  334. }
  335. }
  336. static function getSuperClass( c : Class<Dynamic> ) : Class<Dynamic> {
  337. if( c == null )
  338. return null;
  339. try {
  340. if (builtinHasAttr(c, "_hx_super")) {
  341. return Syntax.field(c, "_hx_super");
  342. }
  343. return null;
  344. } catch (e:Dynamic) {
  345. }
  346. return null;
  347. }
  348. static function getClassFields( c : Class<Dynamic> ) : Array<String> {
  349. if (builtinHasAttr(c, "_hx_statics")) {
  350. var x:Array<String> = Syntax.field(c, "_hx_statics");
  351. return x.copy();
  352. } else {
  353. return [];
  354. }
  355. }
  356. static inline function handleKeywords(name:String):String
  357. {
  358. if (keywords.has(name)) {
  359. return "_hx_" + name;
  360. }
  361. return name;
  362. }
  363. static function unhandleKeywords(name:String):String
  364. {
  365. if (name.substr(0,4) == "_hx_") {
  366. var real = name.substr(4);
  367. if (keywords.has(real)) return real;
  368. }
  369. return name;
  370. }
  371. }