PageRenderTime 58ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/Languages/IronPython/IronPython/Runtime/Types/PythonType.cs

http://github.com/IronLanguages/main
C# | 3624 lines | 2649 code | 622 blank | 353 comment | 753 complexity | 2cef20ee4eb7d89ae2890c8135461ba3 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if FEATURE_CORE_DLR
  16. using System.Linq.Expressions;
  17. #else
  18. using Microsoft.Scripting.Ast;
  19. #endif
  20. using System;
  21. using System.Collections;
  22. using System.Collections.Generic;
  23. using System.Diagnostics;
  24. using System.Globalization;
  25. using System.Linq;
  26. using System.Reflection;
  27. using System.Runtime.CompilerServices;
  28. using System.Dynamic;
  29. using System.Text;
  30. using System.Threading;
  31. using Microsoft.Scripting;
  32. using Microsoft.Scripting.Actions;
  33. using Microsoft.Scripting.Runtime;
  34. using Microsoft.Scripting.Utils;
  35. using IronPython.Runtime.Binding;
  36. using IronPython.Runtime.Operations;
  37. #if FEATURE_NUMERICS
  38. using System.Numerics;
  39. #else
  40. using Microsoft.Scripting.Math;
  41. using Complex = Microsoft.Scripting.Math.Complex64;
  42. #endif
  43. namespace IronPython.Runtime.Types {
  44. /// <summary>
  45. /// Represents a PythonType. Instances of PythonType are created via PythonTypeBuilder.
  46. /// </summary>
  47. [DebuggerDisplay("PythonType: {Name}"), DebuggerTypeProxy(typeof(PythonType.DebugProxy))]
  48. [PythonType("type")]
  49. [Documentation(@"type(object) -> gets the type of the object
  50. type(name, bases, dict) -> creates a new type instance with the given name, base classes, and members from the dictionary")]
  51. public partial class PythonType : IPythonMembersList, IDynamicMetaObjectProvider, IWeakReferenceable, IWeakReferenceableByProxy, ICodeFormattable, IFastGettable, IFastSettable, IFastInvokable {
  52. private Type/*!*/ _underlyingSystemType; // the underlying CLI system type for this type
  53. private string _name; // the name of the type
  54. private Dictionary<string, PythonTypeSlot> _dict; // type-level slots & attributes
  55. private PythonTypeAttributes _attrs; // attributes of the type
  56. private int _flags; // CPython-like flags on the type
  57. private int _version = GetNextVersion(); // version of the type
  58. private List<WeakReference> _subtypes; // all of the subtypes of the PythonType
  59. private PythonContext _pythonContext; // the context the type was created from, or null for system types.
  60. private bool? _objectNew, _objectInit; // true if the type doesn't override __new__ / __init__ from object.
  61. internal Dictionary<CachedGetKey, FastGetBase> _cachedGets; // cached gets on user defined type instances
  62. internal Dictionary<CachedGetKey, FastGetBase> _cachedTryGets; // cached try gets on used defined type instances
  63. internal Dictionary<SetMemberKey, FastSetBase> _cachedSets; // cached sets on user defined instances
  64. internal Dictionary<string, TypeGetBase> _cachedTypeGets; // cached gets on types (system and user types)
  65. internal Dictionary<string, TypeGetBase> _cachedTypeTryGets; // cached gets on types (system and user types)
  66. // commonly calculatable
  67. private List<PythonType> _resolutionOrder; // the search order for methods in the type
  68. private PythonType/*!*/[]/*!*/ _bases; // the base classes of the type
  69. private BuiltinFunction _ctor; // the built-in function which allocates an instance - a .NET ctor
  70. private Type _finalSystemType; // base .NET type if we're inherited from another Python-like type.
  71. // fields that frequently remain null
  72. private WeakRefTracker _weakrefTracker; // storage for Python style weak references
  73. private WeakReference _weakRef; // single weak ref instance used for all user PythonTypes.
  74. private string[] _slots; // the slots when the class was created
  75. private OldClass _oldClass; // the associated OldClass or null for new-style types
  76. private int _originalSlotCount; // the number of slots when the type was created
  77. private InstanceCreator _instanceCtor; // creates instances
  78. private CallSite<Func<CallSite, object, int>> _hashSite;
  79. private CallSite<Func<CallSite, object, object, bool>> _eqSite;
  80. private CallSite<Func<CallSite, object, object, int>> _compareSite;
  81. private Dictionary<CallSignature, LateBoundInitBinder> _lateBoundInitBinders;
  82. private string[] _optimizedInstanceNames; // optimized names stored in a custom dictionary
  83. private int _optimizedInstanceVersion;
  84. private Dictionary<string, List<MethodInfo>> _extensionMethods; // extension methods defined on the type
  85. private PythonSiteCache _siteCache = new PythonSiteCache();
  86. private PythonTypeSlot _lenSlot; // cached length slot, cleared when the type is mutated
  87. internal Func<string, Exception> _makeException = DefaultMakeException;
  88. [MultiRuntimeAware]
  89. private static int MasterVersion = 1;
  90. private static readonly CommonDictionaryStorage _pythonTypes = new CommonDictionaryStorage();
  91. internal static readonly PythonType _pythonTypeType = DynamicHelpers.GetPythonTypeFromType(typeof(PythonType));
  92. private static readonly WeakReference[] _emptyWeakRef = new WeakReference[0];
  93. private static object _subtypesLock = new object();
  94. internal static readonly Func<string, Exception> DefaultMakeException = (message) => new Exception(message);
  95. /// <summary>
  96. /// Provides delegates that will invoke a parameterless type ctor. The first key provides
  97. /// the dictionary for a specific type, the 2nd key provides the delegate for a specific
  98. /// call site type used in conjunction w/ our IFastInvokable implementation.
  99. /// </summary>
  100. private static Dictionary<Type, Dictionary<Type, Delegate>> _fastBindCtors = new Dictionary<Type, Dictionary<Type, Delegate>>();
  101. /// <summary>
  102. /// Shared built-in functions for creating instances of user defined types. Because all
  103. /// types w/ the same UnderlyingSystemType share the same constructors these can be
  104. /// shared across multiple types.
  105. /// </summary>
  106. private static Dictionary<Type, BuiltinFunction> _userTypeCtors = new Dictionary<Type, BuiltinFunction>();
  107. /// <summary>
  108. /// Creates a new type for a user defined type. The name, base classes (a tuple of type
  109. /// objects), and a dictionary of members is provided.
  110. /// </summary>
  111. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
  112. public PythonType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary dict)
  113. : this(context, name, bases, dict, String.Empty) {
  114. }
  115. /// <summary>
  116. /// Creates a new type for a user defined type. The name, base classes (a tuple of type
  117. /// objects), and a dictionary of members is provided.
  118. /// </summary>
  119. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
  120. internal PythonType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary dict, string selfNames) {
  121. InitializeUserType(context, name, bases, dict, selfNames);
  122. }
  123. internal PythonType() {
  124. }
  125. /// <summary>
  126. /// Creates a new PythonType object which is backed by the specified .NET type for
  127. /// storage. The type is considered a system type which can not be modified
  128. /// by the user.
  129. /// </summary>
  130. /// <param name="underlyingSystemType"></param>
  131. internal PythonType(Type underlyingSystemType) {
  132. _underlyingSystemType = underlyingSystemType;
  133. InitializeSystemType();
  134. }
  135. /// <summary>
  136. /// Creates a new PythonType which is a subclass of the specified PythonType.
  137. ///
  138. /// Used for runtime defined new-style classes which require multiple inheritance. The
  139. /// primary example of this is the exception system.
  140. /// </summary>
  141. internal PythonType(PythonType baseType, string name, Func<string, Exception> exceptionMaker) {
  142. _underlyingSystemType = baseType.UnderlyingSystemType;
  143. IsSystemType = baseType.IsSystemType;
  144. IsPythonType = baseType.IsPythonType;
  145. Name = name;
  146. _bases = new PythonType[] { baseType };
  147. ResolutionOrder = Mro.Calculate(this, _bases);
  148. _attrs |= PythonTypeAttributes.HasDictionary;
  149. _makeException = exceptionMaker;
  150. }
  151. /// <summary>
  152. /// Creates a new PythonType which is a subclass of the specified PythonTypes.
  153. ///
  154. /// Used for runtime defined new-style classes which require multiple inheritance. The
  155. /// primary example of this is the exception system.
  156. /// </summary>
  157. internal PythonType(PythonType[] baseTypes, string name) {
  158. bool isSystemType = false;
  159. bool isPythonType = false;
  160. foreach (PythonType baseType in baseTypes) {
  161. isSystemType |= baseType.IsSystemType;
  162. isPythonType |= baseType.IsPythonType;
  163. }
  164. IsSystemType = isSystemType;
  165. IsPythonType = isPythonType;
  166. Name = name;
  167. _bases = baseTypes;
  168. ResolutionOrder = Mro.Calculate(this, _bases);
  169. _attrs |= PythonTypeAttributes.HasDictionary;
  170. }
  171. /// <summary>
  172. /// Creates a new PythonType which is a subclass of the specified PythonTypes.
  173. ///
  174. /// Used for runtime defined new-style classes which require multiple inheritance. The
  175. /// primary example of this is the exception system.
  176. /// </summary>
  177. internal PythonType(PythonType[] baseTypes, Type underlyingType, string name, Func<string, Exception> exceptionMaker)
  178. : this(baseTypes, name) {
  179. _underlyingSystemType = underlyingType;
  180. _makeException = exceptionMaker;
  181. }
  182. /// <summary>
  183. /// Creates a new PythonType which is a subclass of the specified PythonType.
  184. ///
  185. /// Used for runtime defined new-style classes which require multiple inheritance. The
  186. /// primary example of this is the exception system.
  187. /// </summary>
  188. internal PythonType(PythonContext context, PythonType baseType, string name, string module, string doc, Func<string, Exception> exceptionMaker)
  189. : this(baseType, name, exceptionMaker) {
  190. EnsureDict();
  191. _dict["__doc__"] = new PythonTypeUserDescriptorSlot(doc, true);
  192. _dict["__module__"] = new PythonTypeUserDescriptorSlot(module, true);
  193. IsSystemType = false;
  194. IsPythonType = false;
  195. _pythonContext = context;
  196. _attrs |= PythonTypeAttributes.HasDictionary;
  197. }
  198. /// <summary>
  199. /// Creates a new PythonType which is a subclass of the specified PythonTypes.
  200. ///
  201. /// Used for runtime defined new-style classes which require multiple inheritance. The
  202. /// primary example of this is the exception system.
  203. /// </summary>
  204. internal PythonType(PythonContext context, PythonType[] baseTypes, string name, string module, string doc)
  205. : this(baseTypes, name) {
  206. EnsureDict();
  207. _dict["__doc__"] = new PythonTypeUserDescriptorSlot(doc, true);
  208. _dict["__module__"] = new PythonTypeUserDescriptorSlot(module, true);
  209. _pythonContext = context;
  210. _attrs |= PythonTypeAttributes.HasDictionary;
  211. }
  212. /// <summary>
  213. /// Creates a new PythonType which is a subclass of the specified PythonTypes.
  214. ///
  215. /// Used for runtime defined new-style classes which require multiple inheritance. The
  216. /// primary example of this is the exception system.
  217. /// </summary>
  218. internal PythonType(PythonContext context, PythonType[] baseTypes, Type underlyingType, string name, string module, string doc, Func<string, Exception> exceptionMaker)
  219. : this(baseTypes, underlyingType, name, exceptionMaker) {
  220. EnsureDict();
  221. _dict["__doc__"] = new PythonTypeUserDescriptorSlot(doc, true);
  222. _dict["__module__"] = new PythonTypeUserDescriptorSlot(module, true);
  223. IsSystemType = false;
  224. IsPythonType = false;
  225. _pythonContext = context;
  226. _attrs |= PythonTypeAttributes.HasDictionary;
  227. }
  228. /// <summary>
  229. /// Creates a new PythonType object which represents an Old-style class.
  230. /// </summary>
  231. internal PythonType(OldClass oc) {
  232. EnsureDict();
  233. _underlyingSystemType = typeof(OldInstance);
  234. Name = oc.Name;
  235. OldClass = oc;
  236. List<PythonType> ocs = new List<PythonType>(oc.BaseClasses.Count);
  237. foreach (OldClass klass in oc.BaseClasses) {
  238. ocs.Add(klass.TypeObject);
  239. }
  240. List<PythonType> mro = new List<PythonType>();
  241. mro.Add(this);
  242. _bases = ocs.ToArray();
  243. _resolutionOrder = mro;
  244. AddSlot("__class__", new PythonTypeUserDescriptorSlot(this, true));
  245. }
  246. internal BuiltinFunction Ctor {
  247. get {
  248. EnsureConstructor();
  249. return _ctor;
  250. }
  251. }
  252. #region Public API
  253. public static object __new__(CodeContext/*!*/ context, PythonType cls, string name, PythonTuple bases, PythonDictionary dict) {
  254. return __new__(context, cls, name, bases, dict, String.Empty);
  255. }
  256. internal static object __new__(CodeContext/*!*/ context, PythonType cls, string name, PythonTuple bases, PythonDictionary dict, string selfNames) {
  257. if (name == null) {
  258. throw PythonOps.TypeError("type() argument 1 must be string, not None");
  259. }
  260. if (bases == null) {
  261. throw PythonOps.TypeError("type() argument 2 must be tuple, not None");
  262. }
  263. if (dict == null) {
  264. throw PythonOps.TypeError("TypeError: type() argument 3 must be dict, not None");
  265. }
  266. EnsureModule(context, dict);
  267. PythonType meta = FindMetaClass(cls, bases);
  268. if (meta != TypeCache.OldInstance && meta != TypeCache.PythonType) {
  269. if (meta != cls) {
  270. // the user has a custom __new__ which picked the wrong meta class, call the correct metaclass
  271. return PythonCalls.Call(context, meta, name, bases, dict);
  272. }
  273. // we have the right user __new__, call our ctor method which will do the actual
  274. // creation.
  275. return meta.CreateInstance(context, name, bases, dict);
  276. }
  277. // no custom user type for __new__
  278. return new PythonType(context, name, bases, dict, selfNames);
  279. }
  280. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  281. public void __init__(string name, PythonTuple bases, PythonDictionary dict) {
  282. }
  283. internal static PythonType FindMetaClass(PythonType cls, PythonTuple bases) {
  284. PythonType meta = cls;
  285. foreach (object dt in bases) {
  286. PythonType metaCls = DynamicHelpers.GetPythonType(dt);
  287. if (metaCls == TypeCache.OldClass) continue;
  288. if (meta.IsSubclassOf(metaCls)) continue;
  289. if (metaCls.IsSubclassOf(meta)) {
  290. meta = metaCls;
  291. continue;
  292. }
  293. throw PythonOps.TypeError("Error when calling the metaclass bases\n metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases");
  294. }
  295. return meta;
  296. }
  297. public static object __new__(CodeContext/*!*/ context, object cls, object o) {
  298. return DynamicHelpers.GetPythonType(o);
  299. }
  300. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  301. public void __init__(object o) {
  302. }
  303. [SpecialName, PropertyMethod, WrapperDescriptor]
  304. public static PythonTuple Get__bases__(CodeContext/*!*/ context, PythonType/*!*/ type) {
  305. return type.GetBasesTuple();
  306. }
  307. private PythonTuple GetBasesTuple() {
  308. object[] res = new object[BaseTypes.Count];
  309. IList<PythonType> bases = BaseTypes;
  310. for (int i = 0; i < bases.Count; i++) {
  311. PythonType baseType = bases[i];
  312. if (baseType.IsOldClass) {
  313. res[i] = baseType.OldClass;
  314. } else {
  315. res[i] = baseType;
  316. }
  317. }
  318. return PythonTuple.MakeTuple(res);
  319. }
  320. [SpecialName, PropertyMethod, WrapperDescriptor]
  321. public static PythonType Get__base__(CodeContext/*!*/ context, PythonType/*!*/ type) {
  322. foreach (object typeObj in Get__bases__(context, type)) {
  323. PythonType pt = typeObj as PythonType;
  324. if (pt != null) {
  325. return pt;
  326. }
  327. }
  328. return null;
  329. }
  330. /// <summary>
  331. /// Used in copy_reg which is the only consumer of __flags__ in the standard library.
  332. ///
  333. /// Set if the type is user defined
  334. /// </summary>
  335. private const int TypeFlagHeapType = 0x00000200;
  336. /// <summary>
  337. /// Set if the type has __abstractmethods__ defined
  338. /// </summary>
  339. private const int TypeFlagAbstractMethodsDefined = 0x00080000;
  340. private const int TypeFlagAbstractMethodsNonEmpty = 0x00100000;
  341. private bool SetAbstractMethodFlags(string name, object value) {
  342. if (name != "__abstractmethods__") {
  343. return false;
  344. }
  345. int res = _flags | TypeFlagAbstractMethodsDefined;
  346. IEnumerator enumerator;
  347. if (value == null ||
  348. !PythonOps.TryGetEnumerator(DefaultContext.Default, value, out enumerator) ||
  349. !enumerator.MoveNext()) {
  350. // CPython treats None, non-iterables, and empty iterables as empty sets
  351. // of abstract methods, and sets this flag accordingly
  352. res &= ~(TypeFlagAbstractMethodsNonEmpty);
  353. } else {
  354. res |= TypeFlagAbstractMethodsNonEmpty;
  355. }
  356. _flags = res;
  357. return true;
  358. }
  359. /// <summary>
  360. /// Check whether the current type is iterabel
  361. /// </summary>
  362. /// <param name="context"></param>
  363. /// <returns>True if it is iterable</returns>
  364. internal bool IsIterable(CodeContext context)
  365. {
  366. object _dummy = null;
  367. if (PythonOps.TryGetBoundAttr(context, this, "__iter__", out _dummy) &&
  368. !Object.ReferenceEquals(_dummy, NotImplementedType.Value)
  369. && PythonOps.TryGetBoundAttr(context, this, "next", out _dummy) &&
  370. !Object.ReferenceEquals(_dummy, NotImplementedType.Value))
  371. {
  372. return true;
  373. }
  374. return false;
  375. }
  376. private void ClearAbstractMethodFlags(string name) {
  377. if (name == "__abstractmethods__") {
  378. _flags &= ~(TypeFlagAbstractMethodsDefined | TypeFlagAbstractMethodsNonEmpty);
  379. }
  380. }
  381. internal bool HasAbstractMethods(CodeContext/*!*/ context) {
  382. object abstractMethods;
  383. IEnumerator en;
  384. return (_flags & TypeFlagAbstractMethodsNonEmpty) != 0 &&
  385. TryGetBoundCustomMember(context, "__abstractmethods__", out abstractMethods) &&
  386. PythonOps.TryGetEnumerator(context, abstractMethods, out en) &&
  387. en.MoveNext();
  388. }
  389. internal string GetAbstractErrorMessage(CodeContext/*!*/ context) {
  390. if ((_flags & TypeFlagAbstractMethodsNonEmpty) == 0) {
  391. return null;
  392. }
  393. object abstractMethods;
  394. IEnumerator en;
  395. if (!TryGetBoundCustomMember(context, "__abstractmethods__", out abstractMethods) ||
  396. !PythonOps.TryGetEnumerator(context, abstractMethods, out en) ||
  397. !en.MoveNext()) {
  398. return null;
  399. }
  400. string comma = "";
  401. StringBuilder error = new StringBuilder("Can't instantiate abstract class ");
  402. error.Append(Name);
  403. error.Append(" with abstract methods ");
  404. int i = 0;
  405. do {
  406. string s = en.Current as string;
  407. if (s == null) {
  408. Extensible<string> es = en.Current as Extensible<string>;
  409. if (es != null) {
  410. s = es.Value;
  411. }
  412. }
  413. if (s == null) {
  414. return string.Format(
  415. "sequence item {0}: expected string, {1} found",
  416. i, PythonTypeOps.GetName(en.Current)
  417. );
  418. }
  419. error.Append(comma);
  420. error.Append(en.Current);
  421. comma = ", ";
  422. i++;
  423. } while (en.MoveNext());
  424. return error.ToString();
  425. }
  426. [SpecialName, PropertyMethod, WrapperDescriptor]
  427. public static int Get__flags__(CodeContext/*!*/ context, PythonType/*!*/ type) {
  428. int res = type._flags;
  429. if (type.IsSystemType) {
  430. res |= TypeFlagHeapType;
  431. }
  432. return res;
  433. }
  434. [SpecialName, PropertyMethod, WrapperDescriptor]
  435. public static void Set__bases__(CodeContext/*!*/ context, PythonType/*!*/ type, object value) {
  436. // validate we got a tuple...
  437. PythonTuple t = value as PythonTuple;
  438. if (t == null) throw PythonOps.TypeError("expected tuple of types or old-classes, got '{0}'", PythonTypeOps.GetName(value));
  439. List<PythonType> ldt = new List<PythonType>();
  440. foreach (object o in t) {
  441. // gather all the type objects...
  442. PythonType adt = o as PythonType;
  443. if (adt == null) {
  444. OldClass oc = o as OldClass;
  445. if (oc == null) {
  446. throw PythonOps.TypeError("expected tuple of types, got '{0}'", PythonTypeOps.GetName(o));
  447. }
  448. adt = oc.TypeObject;
  449. }
  450. ldt.Add(adt);
  451. }
  452. #if FEATURE_REFEMIT
  453. // Ensure that we are not switching the CLI type
  454. Type newType = NewTypeMaker.GetNewType(type.Name, t);
  455. if (type.UnderlyingSystemType != newType)
  456. throw PythonOps.TypeErrorForIncompatibleObjectLayout("__bases__ assignment", type, newType);
  457. #endif
  458. // set bases & the new resolution order
  459. List<PythonType> mro = CalculateMro(type, ldt);
  460. type.BaseTypes = ldt;
  461. type._resolutionOrder = mro;
  462. }
  463. private static List<PythonType> CalculateMro(PythonType type, IList<PythonType> ldt) {
  464. return Mro.Calculate(type, ldt);
  465. }
  466. private static bool TryReplaceExtensibleWithBase(Type curType, out Type newType) {
  467. if (curType.GetTypeInfo().IsGenericType &&
  468. curType.GetGenericTypeDefinition() == typeof(Extensible<>)) {
  469. newType = curType.GetGenericArguments()[0];
  470. return true;
  471. }
  472. newType = null;
  473. return false;
  474. }
  475. public object __call__(CodeContext context, params object[] args) {
  476. return PythonTypeOps.CallParams(context, this, args);
  477. }
  478. public object __call__(CodeContext context, [ParamDictionary]IDictionary<string, object> kwArgs, params object[] args) {
  479. return PythonTypeOps.CallWorker(context, this, kwArgs, args);
  480. }
  481. public int __cmp__([NotNull]PythonType other) {
  482. if (other != this) {
  483. int res = Name.CompareTo(other.Name);
  484. if (res == 0) {
  485. long thisId = IdDispenser.GetId(this);
  486. long otherId = IdDispenser.GetId(other);
  487. if (thisId > otherId) {
  488. return 1;
  489. } else {
  490. return -1;
  491. }
  492. }
  493. return res;
  494. }
  495. return 0;
  496. }
  497. // Do not override == and != because it causes lots of spurious warnings
  498. // TODO Replace those warnings with .ReferenceEquals calls & overload ==/!=
  499. public bool __eq__([NotNull]PythonType other) {
  500. return this.__cmp__(other) == 0;
  501. }
  502. public bool __ne__([NotNull]PythonType other) {
  503. return this.__cmp__(other) != 0;
  504. }
  505. [Python3Warning("type inequality comparisons not supported in 3.x")]
  506. public static bool operator >(PythonType self, PythonType other) {
  507. return self.__cmp__(other) > 0;
  508. }
  509. [Python3Warning("type inequality comparisons not supported in 3.x")]
  510. public static bool operator <(PythonType self, PythonType other) {
  511. return self.__cmp__(other) < 0;
  512. }
  513. [Python3Warning("type inequality comparisons not supported in 3.x")]
  514. public static bool operator >=(PythonType self, PythonType other) {
  515. return self.__cmp__(other) >= 0;
  516. }
  517. [Python3Warning("type inequality comparisons not supported in 3.x")]
  518. public static bool operator <=(PythonType self, PythonType other) {
  519. return self.__cmp__(other) <= 0;
  520. }
  521. public void __delattr__(CodeContext/*!*/ context, string name) {
  522. DeleteCustomMember(context, name);
  523. }
  524. [SlotField]
  525. public static PythonTypeSlot __dict__ = new PythonTypeDictSlot(_pythonTypeType);
  526. [SpecialName, PropertyMethod, WrapperDescriptor]
  527. public static object Get__doc__(CodeContext/*!*/ context, PythonType self) {
  528. PythonTypeSlot pts;
  529. object res;
  530. if (self.TryLookupSlot(context, "__doc__", out pts) &&
  531. pts.TryGetValue(context, null, self, out res)) {
  532. return res;
  533. } else if (self.IsSystemType) {
  534. return PythonTypeOps.GetDocumentation(self.UnderlyingSystemType);
  535. }
  536. return null;
  537. }
  538. public object __getattribute__(CodeContext/*!*/ context, string name) {
  539. object value;
  540. if (TryGetBoundCustomMember(context, name, out value)) {
  541. return value;
  542. }
  543. throw PythonOps.AttributeError("type object '{0}' has no attribute '{1}'", Name, name);
  544. }
  545. public PythonType this[params Type[] args] {
  546. get {
  547. if (UnderlyingSystemType == typeof(Array)) {
  548. if (args.Length == 1) {
  549. return DynamicHelpers.GetPythonTypeFromType(args[0].MakeArrayType());
  550. }
  551. throw PythonOps.TypeError("expected one argument to make array type, got {0}", args.Length);
  552. }
  553. if (!UnderlyingSystemType.IsGenericTypeDefinition()) {
  554. throw new InvalidOperationException("MakeGenericType on non-generic type");
  555. }
  556. return DynamicHelpers.GetPythonTypeFromType(UnderlyingSystemType.MakeGenericType(args));
  557. }
  558. }
  559. [SpecialName, PropertyMethod, WrapperDescriptor]
  560. public static object Get__module__(CodeContext/*!*/ context, PythonType self) {
  561. PythonTypeSlot pts;
  562. object res;
  563. if (self._dict != null &&
  564. self._dict.TryGetValue("__module__", out pts) &&
  565. pts.TryGetValue(context, self, DynamicHelpers.GetPythonType(self), out res)) {
  566. return res;
  567. }
  568. return PythonTypeOps.GetModuleName(context, self.UnderlyingSystemType);
  569. }
  570. [SpecialName, PropertyMethod, WrapperDescriptor, PythonHidden]
  571. public static string Get__clr_assembly__(PythonType self) {
  572. return self.UnderlyingSystemType.Namespace + " in " + self.UnderlyingSystemType.GetTypeInfo().Assembly.FullName;
  573. }
  574. [SpecialName, PropertyMethod, WrapperDescriptor]
  575. public static void Set__module__(CodeContext/*!*/ context, PythonType self, object value) {
  576. if (self.IsSystemType) {
  577. throw PythonOps.TypeError("can't set {0}.__module__", self.Name);
  578. }
  579. Debug.Assert(self._dict != null);
  580. self._dict["__module__"] = new PythonTypeUserDescriptorSlot(value);
  581. self.UpdateVersion();
  582. }
  583. [SpecialName, PropertyMethod, WrapperDescriptor]
  584. public static void Delete__module__(CodeContext/*!*/ context, PythonType self) {
  585. throw PythonOps.TypeError("can't delete {0}.__module__", self.Name);
  586. }
  587. [SpecialName, PropertyMethod, WrapperDescriptor]
  588. public static PythonTuple Get__mro__(PythonType type) {
  589. return PythonTypeOps.MroToPython(type.ResolutionOrder);
  590. }
  591. [SpecialName, PropertyMethod, WrapperDescriptor]
  592. public static string Get__name__(PythonType type) {
  593. return type.Name;
  594. }
  595. [SpecialName, PropertyMethod, WrapperDescriptor]
  596. public static void Set__name__(PythonType type, string name) {
  597. if (type.IsSystemType) {
  598. throw PythonOps.TypeError("can't set attributes of built-in/extension type '{0}'", type.Name);
  599. }
  600. type.Name = name;
  601. }
  602. public string/*!*/ __repr__(CodeContext/*!*/ context) {
  603. string name = Name;
  604. if (IsSystemType) {
  605. if (PythonTypeOps.IsRuntimeAssembly(UnderlyingSystemType.GetTypeInfo().Assembly) || IsPythonType) {
  606. object module = Get__module__(context, this);
  607. if (!module.Equals("__builtin__")) {
  608. return string.Format("<type '{0}.{1}'>", module, Name);
  609. }
  610. }
  611. return string.Format("<type '{0}'>", Name);
  612. } else {
  613. PythonTypeSlot dts;
  614. string module = "unknown";
  615. object modObj;
  616. if (TryLookupSlot(context, "__module__", out dts) &&
  617. dts.TryGetValue(context, this, this, out modObj)) {
  618. module = modObj as string;
  619. }
  620. return string.Format("<class '{0}.{1}'>", module, name);
  621. }
  622. }
  623. internal string/*!*/ GetTypeDebuggerDisplay() {
  624. PythonTypeSlot dts;
  625. string module = "unknown";
  626. object modObj;
  627. if (TryLookupSlot(Context.SharedContext, "__module__", out dts) &&
  628. dts.TryGetValue(Context.SharedContext, this, this, out modObj)) {
  629. module = modObj as string;
  630. }
  631. return string.Format("{0}.{1} instance", module, Name);
  632. }
  633. public void __setattr__(CodeContext/*!*/ context, string name, object value) {
  634. SetCustomMember(context, name, value);
  635. }
  636. public List __subclasses__(CodeContext/*!*/ context) {
  637. List ret = new List();
  638. IList<WeakReference> subtypes = SubTypes;
  639. if (subtypes != null) {
  640. PythonContext pc = PythonContext.GetContext(context);
  641. foreach (WeakReference wr in subtypes) {
  642. if (wr.IsAlive) {
  643. PythonType pt = (PythonType)wr.Target;
  644. if (pt.PythonContext == null || pt.PythonContext == pc) {
  645. ret.AddNoLock(wr.Target);
  646. }
  647. }
  648. }
  649. }
  650. return ret;
  651. }
  652. public virtual List mro() {
  653. return new List(Get__mro__(this));
  654. }
  655. /// <summary>
  656. /// Returns true if the specified object is an instance of this type.
  657. /// </summary>
  658. public virtual bool __instancecheck__(object instance) {
  659. return SubclassImpl(DynamicHelpers.GetPythonType(instance));
  660. }
  661. public virtual bool __subclasscheck__(PythonType sub) {
  662. return SubclassImpl(sub);
  663. }
  664. private bool SubclassImpl(PythonType sub) {
  665. if (UnderlyingSystemType.IsInterface()) {
  666. // interfaces aren't in bases, and therefore IsSubclassOf doesn't do this check.
  667. if (UnderlyingSystemType.IsAssignableFrom(sub.UnderlyingSystemType)) {
  668. return true;
  669. }
  670. }
  671. return sub.IsSubclassOf(this);
  672. }
  673. public virtual bool __subclasscheck__(OldClass sub) {
  674. return IsSubclassOf(sub.TypeObject);
  675. }
  676. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates")]
  677. public static implicit operator Type(PythonType self) {
  678. return self.UnderlyingSystemType;
  679. }
  680. public static implicit operator TypeTracker(PythonType self) {
  681. return ReflectionCache.GetTypeTracker(self.UnderlyingSystemType);
  682. }
  683. #endregion
  684. #region Internal API
  685. internal bool IsMixedNewStyleOldStyle() {
  686. if (!IsOldClass) {
  687. foreach (PythonType baseType in ResolutionOrder) {
  688. if (baseType.IsOldClass) {
  689. // mixed new-style/old-style class, we can't handle
  690. // __init__ in an old-style class yet (it doesn't show
  691. // up in a slot).
  692. return true;
  693. }
  694. }
  695. }
  696. return false;
  697. }
  698. internal int SlotCount {
  699. get {
  700. return _originalSlotCount;
  701. }
  702. }
  703. /// <summary>
  704. /// Gets the name of the dynamic type
  705. /// </summary>
  706. internal string Name {
  707. get {
  708. return _name;
  709. }
  710. set {
  711. _name = value;
  712. }
  713. }
  714. internal int Version {
  715. get {
  716. return _version;
  717. }
  718. }
  719. internal bool IsNull {
  720. get {
  721. return UnderlyingSystemType == typeof(DynamicNull);
  722. }
  723. }
  724. /// <summary>
  725. /// Gets the resolution order used for attribute lookup
  726. /// </summary>
  727. internal IList<PythonType> ResolutionOrder {
  728. get {
  729. return _resolutionOrder;
  730. }
  731. set {
  732. lock (SyncRoot) {
  733. _resolutionOrder = new List<PythonType>(value);
  734. }
  735. }
  736. }
  737. /// <summary>
  738. /// Gets the dynamic type that corresponds with the provided static type.
  739. ///
  740. /// Returns null if no type is available. TODO: In the future this will
  741. /// always return a PythonType created by the DLR.
  742. /// </summary>
  743. /// <param name="type"></param>
  744. /// <returns></returns>
  745. internal static PythonType/*!*/ GetPythonType(Type type) {
  746. object res;
  747. if (!_pythonTypes.TryGetValue(type, out res)) {
  748. lock (_pythonTypes) {
  749. if (!_pythonTypes.TryGetValue(type, out res)) {
  750. res = new PythonType(type);
  751. _pythonTypes.Add(type, res);
  752. }
  753. }
  754. }
  755. return (PythonType)res;
  756. }
  757. /// <summary>
  758. /// Sets the python type that corresponds with the provided static type.
  759. ///
  760. /// This is used for built-in types which have a metaclass. Currently
  761. /// only used by ctypes.
  762. /// </summary>
  763. internal static PythonType SetPythonType(Type type, PythonType pyType) {
  764. lock (_pythonTypes) {
  765. Debug.Assert(!_pythonTypes.Contains(type));
  766. Debug.Assert(pyType.GetType() != typeof(PythonType));
  767. _pythonTypes.Add(type, pyType);
  768. }
  769. return pyType;
  770. }
  771. /// <summary>
  772. /// Allocates the storage for the instance running the .NET constructor. This provides
  773. /// the creation functionality for __new__ implementations.
  774. /// </summary>
  775. internal object CreateInstance(CodeContext/*!*/ context) {
  776. EnsureInstanceCtor();
  777. return _instanceCtor.CreateInstance(context);
  778. }
  779. /// <summary>
  780. /// Allocates the storage for the instance running the .NET constructor. This provides
  781. /// the creation functionality for __new__ implementations.
  782. /// </summary>
  783. internal object CreateInstance(CodeContext/*!*/ context, object arg0) {
  784. EnsureInstanceCtor();
  785. return _instanceCtor.CreateInstance(context, arg0);
  786. }
  787. /// <summary>
  788. /// Allocates the storage for the instance running the .NET constructor. This provides
  789. /// the creation functionality for __new__ implementations.
  790. /// </summary>
  791. internal object CreateInstance(CodeContext/*!*/ context, object arg0, object arg1) {
  792. EnsureInstanceCtor();
  793. return _instanceCtor.CreateInstance(context, arg0, arg1);
  794. }
  795. /// <summary>
  796. /// Allocates the storage for the instance running the .NET constructor. This provides
  797. /// the creation functionality for __new__ implementations.
  798. /// </summary>
  799. internal object CreateInstance(CodeContext/*!*/ context, object arg0, object arg1, object arg2) {
  800. EnsureInstanceCtor();
  801. return _instanceCtor.CreateInstance(context, arg0, arg1, arg2);
  802. }
  803. /// <summary>
  804. /// Allocates the storage for the instance running the .NET constructor. This provides
  805. /// the creation functionality for __new__ implementations.
  806. /// </summary>
  807. internal object CreateInstance(CodeContext context, params object[] args) {
  808. Assert.NotNull(args);
  809. EnsureInstanceCtor();
  810. // unpack args for common cases so we don't generate code to do it...
  811. switch (args.Length) {
  812. case 0: return _instanceCtor.CreateInstance(context);
  813. case 1: return _instanceCtor.CreateInstance(context, args[0]);
  814. case 2: return _instanceCtor.CreateInstance(context, args[0], args[1]);
  815. case 3: return _instanceCtor.CreateInstance(context, args[0], args[1], args[2]);
  816. default:
  817. return _instanceCtor.CreateInstance(context, args);
  818. }
  819. }
  820. /// <summary>
  821. /// Allocates the storage for the instance running the .NET constructor. This provides
  822. /// the creation functionality for __new__ implementations.
  823. /// </summary>
  824. internal object CreateInstance(CodeContext context, object[] args, string[] names) {
  825. Assert.NotNull(args, "args");
  826. Assert.NotNull(names, "names");
  827. EnsureInstanceCtor();
  828. return _instanceCtor.CreateInstance(context, args, names);
  829. }
  830. internal int Hash(object o) {
  831. EnsureHashSite();
  832. return _hashSite.Target(_hashSite, o);
  833. }
  834. internal bool TryGetLength(CodeContext context, object o, out int length) {
  835. CallSite<Func<CallSite, CodeContext, object, object>> lenSite;
  836. if (IsSystemType) {
  837. lenSite = PythonContext.GetContext(context).GetSiteCacheForSystemType(UnderlyingSystemType).GetLenSite(context);
  838. } else {
  839. lenSite = _siteCache.GetLenSite(context);
  840. }
  841. PythonTypeSlot lenSlot = _lenSlot;
  842. if (lenSlot == null && !PythonOps.TryResolveTypeSlot(context, this, "__len__", out lenSlot)) {
  843. length = 0;
  844. return false;
  845. }
  846. object func;
  847. if (!lenSlot.TryGetValue(context, o, this, out func)) {
  848. length = 0;
  849. return false;
  850. }
  851. object res = lenSite.Target(lenSite, context, func);
  852. if (!(res is int)) {
  853. throw PythonOps.ValueError("__len__ must return int");
  854. }
  855. length = (int)res;
  856. return true;
  857. }
  858. internal bool EqualRetBool(object self, object other) {
  859. if (_eqSite == null) {
  860. Interlocked.CompareExchange(
  861. ref _eqSite,
  862. Context.CreateComparisonSite(PythonOperationKind.Equal),
  863. null
  864. );
  865. }
  866. return _eqSite.Target(_eqSite, self, other);
  867. }
  868. internal int Compare(object self, object other) {
  869. if (_compareSite == null) {
  870. Interlocked.CompareExchange(
  871. ref _compareSite,
  872. Context.MakeSortCompareSite(),
  873. null
  874. );
  875. }
  876. return _compareSite.Target(_compareSite, self, other);
  877. }
  878. internal bool TryGetBoundAttr(CodeContext context, object o, string name, out object ret) {
  879. CallSite<Func<CallSite, object, CodeContext, object>> site;
  880. if (IsSystemType) {
  881. site = PythonContext.GetContext(context).GetSiteCacheForSystemType(UnderlyingSystemType).GetTryGetMemberSite(context, name);
  882. } else {
  883. site = _siteCache.GetTryGetMemberSite(context, name);
  884. }
  885. try {
  886. ret = site.Target(site, o, context);
  887. return ret != OperationFailed.Value;
  888. } catch (MissingMemberException) {
  889. ret = null;
  890. return false;
  891. }
  892. }
  893. internal CallSite<Func<CallSite, object, int>> HashSite {
  894. get {
  895. EnsureHashSite();
  896. return _hashSite;
  897. }
  898. }
  899. private void EnsureHashSite() {
  900. if(_hashSite == null) {
  901. Interlocked.CompareExchange(
  902. ref _hashSite,
  903. CallSite<Func<CallSite, object, int>>.Create(
  904. Context.Operation(
  905. PythonOperationKind.Hash
  906. )
  907. ),
  908. null
  909. );
  910. }
  911. }
  912. /// <summary>
  913. /// Gets the underlying system type that is backing this type. All instances of this
  914. /// type are an instance of the underlying system type.
  915. /// </summary>
  916. internal Type/*!*/ UnderlyingSystemType {
  917. get {
  918. return _underlyingSystemType;
  919. }
  920. }
  921. internal Type/*!*/ FinalSystemType {
  922. get {
  923. return _finalSystemType ?? (_finalSystemType = PythonTypeOps.GetFinalSystemType(_underlyingSystemType));
  924. }
  925. }
  926. /// <summary>
  927. /// Gets the extension type for this type. The extension type provides
  928. /// a .NET type which can be inherited from to extend sealed classes
  929. /// or value types which Python allows inheritance from.
  930. /// </summary>
  931. internal Type/*!*/ ExtensionType {
  932. get {
  933. if (!_underlyingSystemType.IsEnum()) {
  934. switch (_underlyingSystemType.GetTypeCode()) {
  935. case TypeCode.String: return typeof(ExtensibleString);
  936. case TypeCode.Int32: return typeof(Extensible<int>);
  937. case TypeCode.Double: return typeof(Extensible<double>);
  938. case TypeCode.Object:
  939. if (_underlyingSystemType == typeof(BigInteger)) {
  940. return typeof(Extensible<BigInteger>);
  941. } else if (_underlyingSystemType == typeof(Complex)) {
  942. return typeof(ExtensibleComplex);
  943. }
  944. break;
  945. }
  946. }
  947. return _underlyingSystemType;
  948. }
  949. }
  950. /// <summary>
  951. /// Gets the base types from which this type inherits.
  952. /// </summary>
  953. internal IList<PythonType>/*!*/ BaseTypes {
  954. get {
  955. return _bases;
  956. }
  957. set {
  958. // validate input...
  959. foreach (PythonType pt in value) {
  960. if (pt == null) throw new ArgumentNullException("value", "a PythonType was null while assigning base classes");
  961. }
  962. // first update our sub-type list
  963. lock (_bases) {
  964. foreach (PythonType dt in _bases) {
  965. dt.RemoveSubType(this);
  966. }
  967. // set the new bases
  968. List<PythonType> newBases = new List<PythonType>(value);
  969. // add us as subtypes of our new bases
  970. foreach (PythonType dt in newBases) {
  971. dt.AddSubType(this);
  972. }
  973. UpdateVersion();
  974. _bases = newBases.ToArray();
  975. }
  976. }
  977. }
  978. /// <summary>
  979. /// Returns true if this type is a subclass of other
  980. /// </summary>
  981. internal bool IsSubclassOf(PythonType other) {
  982. // check for a type match
  983. if (other == this) {
  984. return true;
  985. }
  986. //Python doesn't have value types inheriting from ValueType, but we fake this for interop
  987. if (other.UnderlyingSystemType == typeof(ValueType) && UnderlyingSystemType.IsValueType()) {
  988. return true;
  989. }
  990. return IsSubclassWorker(other);
  991. }
  992. private bool IsSubclassWorker(PythonType other) {
  993. for (int i = 0; i < _bases.Length; i++) {
  994. PythonType baseClass = _bases[i];
  995. if (baseClass == other || baseClass.IsSubclassWorker(other)) {
  996. return true;
  997. }
  998. }
  999. return false;
  1000. }
  1001. /// <summary>
  1002. /// True if the type is a system type. A system type is a type which represents an
  1003. /// underlying .NET type and not a subtype of one of these types.
  1004. /// </summary>
  1005. internal bool IsSystemType {
  1006. get {
  1007. return (_attrs & PythonTypeAttributes.SystemType) != 0;
  1008. }
  1009. set {
  1010. if (value) _attrs |= PythonTypeAttributes.SystemType;
  1011. else _attrs &= (~PythonTypeAttributes.SystemType);
  1012. }
  1013. }
  1014. internal bool IsWeakReferencable {
  1015. get {
  1016. return (_attrs & PythonTypeAttributes.WeakReferencable) != 0;
  1017. }
  1018. set {
  1019. if (value) _attrs |= PythonTypeAttributes.WeakReferencable;
  1020. else _attrs &= (~PythonTypeAttributes.WeakReferencable);
  1021. }
  1022. }
  1023. internal bool HasDictionary {
  1024. get {
  1025. return (_attrs & PythonTypeAttributes.HasDictionary) != 0;
  1026. }
  1027. set {
  1028. if (value) _attrs |= PythonTypeAttributes.HasDictionary;
  1029. else _attrs &= (~PythonTypeAttributes.HasDictionary);
  1030. }
  1031. }
  1032. internal bool HasSystemCtor {
  1033. get {
  1034. return (_attrs & PythonTypeAttributes.SystemCtor) != 0;
  1035. }
  1036. }
  1037. internal void SetConstructor(BuiltinFunction ctor) {
  1038. _ctor = ctor;
  1039. }
  1040. internal bool IsPythonType {
  1041. get {
  1042. return (_attrs & PythonTypeAttributes.IsPythonType) != 0;
  1043. }
  1044. set {
  1045. if (value) {
  1046. _attrs |= PythonTypeAttributes.IsPythonType;
  1047. } else {
  1048. _attrs &= ~PythonTypeAttributes.IsPythonType;
  1049. }
  1050. }
  1051. }
  1052. internal OldClass OldClass {
  1053. get {
  1054. return _oldClass;
  1055. }
  1056. set {
  1057. _oldClass = value;
  1058. }
  1059. }
  1060. internal bool IsOldClass {
  1061. get {
  1062. return _oldClass != null;
  1063. }
  1064. }

Large files files are truncated, but you can click here to view the full file