123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474 |
- /*
- * Copyright (C)2005-2019 Haxe Foundation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- package python;
- import python.internal.MethodClosure;
- import python.internal.ArrayImpl;
- import python.internal.Internal;
- import python.internal.StringImpl;
- import python.internal.EnumImpl;
- import python.internal.HxOverrides;
- import python.internal.HxException;
- import python.internal.AnonObject;
- import python.internal.UBuiltins;
- import python.lib.Inspect;
- import python.Syntax;
- @:dox(hide)
- class Boot {
- static var keywords:Set<String> = new Set([
- "and", "del", "from", "not", "with", "as", "elif", "global", "or", "yield", "assert", "else", "if", "pass", "None", "break", "except", "import",
- "raise", "True", "class", "exec", "in", "return", "False", "continue", "finally", "is", "try", "def", "for", "lambda", "while",
- ]);
- inline static function arrayJoin<T>(x:Array<T>, sep:String):String {
- return Syntax.field(sep, "join")(Syntax.code("[{0}(x1,'') for x1 in {1}]", python.Boot.toString1, x));
- }
- inline static function safeJoin(x:Array<String>, sep:String):String {
- return Syntax.field(sep, "join")(Syntax.code("[x1 for x1 in {0}]", x));
- }
- inline static function isPyBool(o:Dynamic):Bool {
- return UBuiltins.isinstance(o, UBuiltins.bool);
- }
- inline static function isPyInt(o:Dynamic):Bool {
- // for historic reasons bool extends int
- return UBuiltins.isinstance(o, UBuiltins.int) && !isPyBool(o);
- }
- inline static function isPyFloat(o:Dynamic):Bool {
- return UBuiltins.isinstance(o, UBuiltins.float);
- }
- static inline function isClass(o:Dynamic):Bool {
- return o != null && (o == String || Inspect.isclass(o));
- }
- static inline function isAnonObject(o:Dynamic) {
- return UBuiltins.isinstance(o, AnonObject);
- }
- @:ifFeature("add_dynamic") private static function _add_dynamic(a:Dynamic, b:Dynamic):Dynamic {
- if (UBuiltins.isinstance(a, String) && UBuiltins.isinstance(b, String)) {
- return Syntax.binop(a, "+", b);
- }
- if (UBuiltins.isinstance(a, String) || UBuiltins.isinstance(b, String)) {
- return Syntax.binop(toString1(a, ""), "+", toString1(b, ""));
- }
- return Syntax.binop(a, "+", b);
- }
- static inline function toString(o:Dynamic) {
- return toString1(o, "");
- }
- private static function toString1(o:Dynamic, s:String):String {
- if (o == null)
- return "null";
- if (isString(o))
- return o;
- if (s == null)
- s = "";
- if (s.length >= 5)
- return "<...>"; // too much deep recursion
- if (isPyBool(o)) {
- if ((o : Bool))
- return "true"
- else
- return "false";
- }
- if (isPyInt(o)) {
- return UBuiltins.str(o);
- }
- // 1.0 should be printed as 1
- if (isPyFloat(o)) {
- try {
- if ((o : Float) == UBuiltins.int(o)) {
- return UBuiltins.str(Math.round(o));
- } else {
- return UBuiltins.str(o);
- }
- } catch (e:Dynamic) {
- return UBuiltins.str(o);
- }
- }
- if (isArray(o)) {
- var o1:Array<Dynamic> = o;
- var l = o1.length;
- var st = "[";
- s += "\t";
- for (i in 0...l) {
- var prefix = "";
- if (i > 0) {
- prefix = ",";
- }
- st += prefix + toString1(o1[i], s);
- }
- st += "]";
- return st;
- }
- try {
- if (UBuiltins.hasattr(o, "toString"))
- return Syntax.callField(o, "toString");
- } catch (e:Dynamic) {}
- if (UBuiltins.hasattr(o, "__class__")) {
- if (isAnonObject(o)) {
- var toStr = null;
- try {
- var fields = fields(o);
- var fieldsStr = [for (f in fields) '$f : ${toString1(simpleField(o, f), s + "\t")}'];
- toStr = "{ " + safeJoin(fieldsStr, ", ") + " }";
- } catch (e:Dynamic) {
- return "{ ... }";
- }
- if (toStr == null) {
- return "{ ... }";
- } else {
- return toStr;
- }
- }
- if (UBuiltins.isinstance(o, Enum)) {
- var o:EnumImpl = (o : EnumImpl);
- var l = UBuiltins.len(o.params);
- var hasParams = l > 0;
- if (hasParams) {
- var paramsStr = "";
- for (i in 0...l) {
- var prefix = "";
- if (i > 0) {
- prefix = ",";
- }
- paramsStr += prefix + toString1(o.params[i], s);
- }
- return o.tag + "(" + paramsStr + ")";
- } else {
- return o.tag;
- }
- }
- if (Internal.hasClassName(o)) {
- if (Syntax.field(Syntax.field(o, "__class__"), "__name__") != "type") {
- var fields = getInstanceFields(o);
- var fieldsStr = [for (f in fields) '$f : ${toString1(simpleField(o, f), s + "\t")}'];
- var toStr = (Internal.fieldClassName(o) : String) + "( " + safeJoin(fieldsStr, ", ") + " )";
- return toStr;
- } else {
- var fields = getClassFields(o);
- var fieldsStr = [for (f in fields) '$f : ${toString1(simpleField(o, f), s + "\t")}'];
- var toStr = "#" + (Internal.fieldClassName(o) : String) + "( " + safeJoin(fieldsStr, ", ") + " )";
- return toStr;
- }
- }
- if (isMetaType(o, String)) {
- return "#String";
- }
- if (isMetaType(o, Array)) {
- return "#Array";
- }
- if (UBuiltins.callable(o)) {
- return "function";
- }
- try {
- if (UBuiltins.hasattr(o, "__repr__")) {
- return Syntax.callField(o, "__repr__");
- }
- } catch (e:Dynamic) {}
- if (UBuiltins.hasattr(o, "__str__")) {
- return Syntax.callField(o, "__str__", []);
- }
- if (UBuiltins.hasattr(o, "__name__")) {
- return Syntax.field(o, "__name__");
- }
- return "???";
- } else {
- return UBuiltins.str(o);
- }
- }
- static inline function isMetaType(v:Dynamic, t:Dynamic):Bool {
- return python.Syntax.binop(v, "==", t);
- }
- @:analyzer(no_local_dce)
- static function fields(o:Dynamic) {
- var a = [];
- if (o != null) {
- if (Internal.hasFields(o)) {
- var fields = Internal.fieldFields(o);
- if (fields != null) {
- return (fields : Array<String>).copy();
- }
- }
- if (isAnonObject(o)) {
- var d = Syntax.field(o, "__dict__");
- var keys = Syntax.callField(d, "keys");
- var handler = unhandleKeywords;
- Syntax.code("for k in keys:");
- Syntax.code(" if (k != '_hx_disable_getattr'):");
- Syntax.code(" a.append(handler(k))");
- } else if (UBuiltins.hasattr(o, "__dict__")) {
- var a = [];
- var d = Syntax.field(o, "__dict__");
- var keys1 = Syntax.callField(d, "keys");
- Syntax.code("for k in keys1:");
- Syntax.code(" a.append(k)");
- }
- }
- return a;
- }
- static inline function isString(o:Dynamic):Bool {
- return UBuiltins.isinstance(o, UBuiltins.str);
- }
- static inline function isArray(o:Dynamic):Bool {
- return UBuiltins.isinstance(o, UBuiltins.list);
- }
- static function simpleField(o:Dynamic, field:String):Dynamic {
- if (field == null)
- return null;
- var field = handleKeywords(field);
- return if (UBuiltins.hasattr(o, field)) UBuiltins.getattr(o, field) else null;
- }
- @:ifFeature("closure_Array", "closure_String")
- static inline function createClosure(obj:Dynamic, func:Dynamic):Dynamic {
- return new MethodClosure(obj, func);
- }
- static function hasField(o:Dynamic, field:String):Bool {
- if (isAnonObject(o)) {
- return Syntax.code('{0}._hx_hasattr({1})', o, field);
- }
- return UBuiltins.hasattr(o, handleKeywords(field));
- }
- static function field(o:Dynamic, field:String):Dynamic {
- if (field == null)
- return null;
- inline function def() {
- var field = handleKeywords(field);
- return if (UBuiltins.hasattr(o, field)) UBuiltins.getattr(o, field) else null;
- }
- return if (isString(o)) {
- switch (field) {
- case "length":
- StringImpl.get_length(o);
- case "toLowerCase":
- createClosure(o, StringImpl.toLowerCase);
- case "toUpperCase":
- createClosure(o, StringImpl.toUpperCase);
- case "charAt":
- createClosure(o, StringImpl.charAt);
- case "charCodeAt":
- createClosure(o, StringImpl.charCodeAt);
- case "indexOf":
- createClosure(o, StringImpl.indexOf);
- case "lastIndexOf":
- createClosure(o, StringImpl.lastIndexOf);
- case "split":
- createClosure(o, StringImpl.split);
- case "substr":
- createClosure(o, StringImpl.substr);
- case "substring":
- createClosure(o, StringImpl.substring);
- case "toString":
- createClosure(o, StringImpl.toString);
- default:
- def();
- }
- } else if (isArray(o)) {
- switch (field) {
- case "length":
- ArrayImpl.get_length(o);
- case "map":
- createClosure(o, ArrayImpl.map);
- case "filter":
- createClosure(o, ArrayImpl.filter);
- case "concat":
- createClosure(o, ArrayImpl.concat);
- case "copy":
- createClosure(o, ArrayImpl.copy);
- case "iterator":
- createClosure(o, ArrayImpl.iterator);
- case "insert":
- createClosure(o, ArrayImpl.insert);
- case "join":
- createClosure(o, ArrayImpl.join);
- case "toString":
- createClosure(o, ArrayImpl.toString);
- case "pop":
- createClosure(o, ArrayImpl.pop);
- case "push":
- createClosure(o, ArrayImpl.push);
- case "unshift":
- createClosure(o, ArrayImpl.unshift);
- case "indexOf":
- createClosure(o, ArrayImpl.indexOf);
- case "lastIndexOf":
- createClosure(o, ArrayImpl.lastIndexOf);
- case "remove":
- createClosure(o, ArrayImpl.remove);
- case "reverse":
- createClosure(o, ArrayImpl.reverse);
- case "shift":
- createClosure(o, ArrayImpl.shift);
- case "slice":
- createClosure(o, ArrayImpl.slice);
- case "sort":
- createClosure(o, ArrayImpl.sort);
- case "splice":
- createClosure(o, ArrayImpl.splice);
- default:
- def();
- }
- } else {
- def();
- }
- }
- static function getInstanceFields(c:Class<Dynamic>):Array<String> {
- var f = if (Internal.hasFields(c)) (Internal.fieldFields(c) : Array<String>).copy() else [];
- if (Internal.hasMethods(c))
- f = f.concat(Internal.fieldMethods(c));
- var sc = getSuperClass(c);
- if (sc == null) {
- return f;
- } else {
- var scArr = getInstanceFields(sc);
- var scMap = new Set(scArr);
- for (f1 in f) {
- if (!scMap.has(f1)) {
- scArr.push(f1);
- }
- }
- return scArr;
- }
- }
- static function getSuperClass(c:Class<Dynamic>):Class<Dynamic> {
- if (c == null)
- return null;
- try {
- if (Internal.hasSuper(c)) {
- return Internal.fieldSuper(c);
- }
- return null;
- } catch (e:Dynamic) {}
- return null;
- }
- static function getClassFields(c:Class<Dynamic>):Array<String> {
- if (Internal.hasStatics(c)) {
- var x:Array<String> = Internal.fieldStatics(c);
- return x.copy();
- } else {
- return [];
- }
- }
- static inline function unsafeFastCodeAt(s:String, index:Int) {
- return UBuiltins.ord(python.Syntax.arrayAccess(s, index));
- }
- static inline function handleKeywords(name:String):String {
- return if (keywords.has(name)) {
- Internal.getPrefixed(name);
- } else if (name.length > 2
- && unsafeFastCodeAt(name, 0) == "_".code
- && unsafeFastCodeAt(name, 1) == "_".code
- && unsafeFastCodeAt(name, name.length - 1) != "_".code) {
- Internal.getPrefixed(name);
- } else
- name;
- }
- static var prefixLength = Internal.prefix().length;
- static function unhandleKeywords(name:String):String {
- if (name.substr(0, prefixLength) == Internal.prefix()) {
- var real = name.substr(prefixLength);
- if (keywords.has(real))
- return real;
- }
- return name;
- }
- static inline function implementsInterface(value:Dynamic, cls:Class<Dynamic>):Bool {
- function loop(intf) {
- var f:Array<Dynamic> = if (Internal.hasInterfaces(intf)) Internal.fieldInterfaces(intf) else [];
- if (f != null) {
- for (i in f) {
- if (i == cls) {
- return true;
- } else {
- var l = loop(i);
- if (l) {
- return true;
- }
- }
- }
- return false;
- } else {
- return false;
- }
- }
- var currentClass = Syntax.field(value, "__class__");
- var result = false;
- while (currentClass != null) {
- if (loop(currentClass)) {
- result = true;
- break;
- }
- currentClass = getSuperClass(currentClass);
- }
- return result;
- }
- }
|