/DICK.B1/IronPython/Runtime/Types/PythonType.cs
C# | 3232 lines | 2364 code | 557 blank | 311 comment | 676 complexity | 752f5f948f96afb4e8139d82ff0a3283 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Microsoft Public License. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Microsoft Public License, please send an email to
- * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Microsoft Public License.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
-
- #if !CLR2
- using System.Linq.Expressions;
- using System.Numerics;
- #else
- using Microsoft.Scripting.Ast;
- using Microsoft.Scripting.Math;
- using Complex = Microsoft.Scripting.Math.Complex64;
- #endif
-
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Globalization;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Dynamic;
- using System.Threading;
-
- using Microsoft.Scripting;
- using Microsoft.Scripting.Actions;
- using Microsoft.Scripting.Generation;
- using Microsoft.Scripting.Runtime;
- using Microsoft.Scripting.Utils;
-
- using IronPython.Runtime.Binding;
- using IronPython.Runtime.Operations;
-
- namespace IronPython.Runtime.Types {
-
- /// <summary>
- /// Represents a PythonType. Instances of PythonType are created via PythonTypeBuilder.
- /// </summary>
- [DebuggerDisplay("PythonType: {Name}"), DebuggerTypeProxy(typeof(PythonType.DebugProxy))]
- [PythonType("type")]
- [Documentation(@"type(object) -> gets the type of the object
- type(name, bases, dict) -> creates a new type instance with the given name, base classes, and members from the dictionary")]
- public partial class PythonType : IPythonMembersList, IDynamicMetaObjectProvider, IWeakReferenceable, ICodeFormattable, IFastGettable, IFastSettable, IFastInvokable {
- private Type/*!*/ _underlyingSystemType; // the underlying CLI system type for this type
- private string _name; // the name of the type
- private Dictionary<string, PythonTypeSlot> _dict; // type-level slots & attributes
- private PythonTypeAttributes _attrs; // attributes of the type
- private int _version = GetNextVersion(); // version of the type
- private List<WeakReference> _subtypes; // all of the subtypes of the PythonType
- private PythonContext _pythonContext; // the context the type was created from, or null for system types.
- private bool? _objectNew, _objectInit; // true if the type doesn't override __new__ / __init__ from object.
- internal Dictionary<string, FastGetBase> _cachedGets; // cached gets on user defined type instances
- internal Dictionary<string, FastGetBase> _cachedTryGets; // cached try gets on used defined type instances
- internal Dictionary<SetMemberKey, FastSetBase> _cachedSets; // cached sets on user defined instances
- internal Dictionary<string, TypeGetBase> _cachedTypeGets; // cached gets on types (system and user types)
- internal Dictionary<string, TypeGetBase> _cachedTypeTryGets; // cached gets on types (system and user types)
-
- // commonly calculatable
- private List<PythonType> _resolutionOrder; // the search order for methods in the type
- private PythonType/*!*/[]/*!*/ _bases; // the base classes of the type
- private BuiltinFunction _ctor; // the built-in function which allocates an instance - a .NET ctor
-
- // fields that frequently remain null
- private WeakRefTracker _weakrefTracker; // storage for Python style weak references
- private WeakReference _weakRef; // single weak ref instance used for all user PythonTypes.
- private string[] _slots; // the slots when the class was created
- private OldClass _oldClass; // the associated OldClass or null for new-style types
- private int _originalSlotCount; // the number of slots when the type was created
- private InstanceCreator _instanceCtor; // creates instances
- private CallSite<Func<CallSite, object, int>> _hashSite;
- private CallSite<Func<CallSite, object, object, bool>> _eqSite;
- private CallSite<Func<CallSite, object, object, int>> _compareSite;
- private Dictionary<CallSignature, LateBoundInitBinder> _lateBoundInitBinders;
- private string[] _optimizedInstanceNames; // optimized names stored in a custom dictionary
- private int _optimizedInstanceVersion;
-
- private PythonSiteCache _siteCache = new PythonSiteCache();
-
- private PythonTypeSlot _lenSlot; // cached length slot, cleared when the type is mutated
-
- [MultiRuntimeAware]
- private static int MasterVersion = 1;
- private static readonly CommonDictionaryStorage _pythonTypes = new CommonDictionaryStorage();
- internal static PythonType _pythonTypeType = DynamicHelpers.GetPythonTypeFromType(typeof(PythonType));
- private static readonly WeakReference[] _emptyWeakRef = new WeakReference[0];
- private static object _subtypesLock = new object();
- /// <summary>
- /// Provides delegates that will invoke a parameterless type ctor. The first key provides
- /// the dictionary for a specific type, the 2nd key provides the delegate for a specific
- /// call site type used in conjunction w/ our IFastInvokable implementation.
- /// </summary>
- private static Dictionary<Type, Dictionary<Type, Delegate>> _fastBindCtors = new Dictionary<Type, Dictionary<Type, Delegate>>();
-
- /// <summary>
- /// Shared built-in functions for creating instances of user defined types. Because all
- /// types w/ the same UnderlyingSystemType share the same constructors these can be
- /// shared across multiple types.
- /// </summary>
- private static Dictionary<Type, BuiltinFunction> _userTypeCtors = new Dictionary<Type, BuiltinFunction>();
-
-
- /// <summary>
- /// Creates a new type for a user defined type. The name, base classes (a tuple of type
- /// objects), and a dictionary of members is provided.
- /// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
- public PythonType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary dict)
- : this(context, name, bases, dict, String.Empty) {
- }
-
- /// <summary>
- /// Creates a new type for a user defined type. The name, base classes (a tuple of type
- /// objects), and a dictionary of members is provided.
- /// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
- internal PythonType(CodeContext/*!*/ context, string name, PythonTuple bases, PythonDictionary dict, string selfNames) {
- InitializeUserType(context, name, bases, dict, selfNames);
- }
-
- internal PythonType() {
- }
-
- /// <summary>
- /// Creates a new PythonType object which is backed by the specified .NET type for
- /// storage. The type is considered a system type which can not be modified
- /// by the user.
- /// </summary>
- /// <param name="underlyingSystemType"></param>
- internal PythonType(Type underlyingSystemType) {
- _underlyingSystemType = underlyingSystemType;
-
- InitializeSystemType();
- }
-
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonType.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonType baseType, string name) {
- _underlyingSystemType = baseType.UnderlyingSystemType;
-
- IsSystemType = baseType.IsSystemType;
- IsPythonType = baseType.IsPythonType;
- Name = name;
- _bases = new PythonType[] { baseType };
- ResolutionOrder = Mro.Calculate(this, _bases);
- _attrs |= PythonTypeAttributes.HasDictionary;
- }
-
- /// <summary>
- /// Creates a new PythonType which is a subclass of the specified PythonType.
- ///
- /// Used for runtime defined new-style classes which require multiple inheritance. The
- /// primary example of this is the exception system.
- /// </summary>
- internal PythonType(PythonContext context, PythonType baseType, string name, string module, string doc)
- : this(baseType, name) {
- EnsureDict();
-
- _dict["__doc__"] = new PythonTypeUserDescriptorSlot(doc, true);
- _dict["__module__"] = new PythonTypeUserDescriptorSlot(module, true);
- IsSystemType = false;
- IsPythonType = false;
- _pythonContext = context;
- _attrs |= PythonTypeAttributes.HasDictionary;
- }
-
- /// <summary>
- /// Creates a new PythonType object which represents an Old-style class.
- /// </summary>
- internal PythonType(OldClass oc) {
- EnsureDict();
-
- _underlyingSystemType = typeof(OldInstance);
- Name = oc.Name;
- OldClass = oc;
-
- List<PythonType> ocs = new List<PythonType>(oc.BaseClasses.Count);
- foreach (OldClass klass in oc.BaseClasses) {
- ocs.Add(klass.TypeObject);
- }
-
- List<PythonType> mro = new List<PythonType>();
- mro.Add(this);
-
- _bases = ocs.ToArray();
- _resolutionOrder = mro;
- AddSlot("__class__", new PythonTypeUserDescriptorSlot(this, true));
- }
-
- internal BuiltinFunction Ctor {
- get {
- EnsureConstructor();
-
- return _ctor;
- }
- }
-
- #region Public API
-
- public static object __new__(CodeContext/*!*/ context, PythonType cls, string name, PythonTuple bases, PythonDictionary dict) {
- return __new__(context, cls, name, bases, dict, String.Empty);
- }
-
- internal static object __new__(CodeContext/*!*/ context, PythonType cls, string name, PythonTuple bases, PythonDictionary dict, string selfNames) {
- if (name == null) {
- throw PythonOps.TypeError("type() argument 1 must be string, not None");
- }
- if (bases == null) {
- throw PythonOps.TypeError("type() argument 2 must be tuple, not None");
- }
- if (dict == null) {
- throw PythonOps.TypeError("TypeError: type() argument 3 must be dict, not None");
- }
-
- EnsureModule(context, dict);
-
- PythonType meta = FindMetaClass(cls, bases);
-
- if (meta != TypeCache.OldInstance && meta != TypeCache.PythonType) {
- if (meta != cls) {
- // the user has a custom __new__ which picked the wrong meta class, call the correct metaclass
- return PythonCalls.Call(context, meta, name, bases, dict);
- }
-
- // we have the right user __new__, call our ctor method which will do the actual
- // creation.
- return meta.CreateInstance(context, name, bases, dict);
- }
-
- // no custom user type for __new__
- return new PythonType(context, name, bases, dict, selfNames);
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
- public void __init__(string name, PythonTuple bases, PythonDictionary dict) {
- }
-
- internal static PythonType FindMetaClass(PythonType cls, PythonTuple bases) {
- PythonType meta = cls;
- foreach (object dt in bases) {
- PythonType metaCls = DynamicHelpers.GetPythonType(dt);
-
- if (metaCls == TypeCache.OldClass) continue;
-
- if (meta.IsSubclassOf(metaCls)) continue;
-
- if (metaCls.IsSubclassOf(meta)) {
- meta = metaCls;
- continue;
- }
- throw PythonOps.TypeError("metaclass conflict {0} and {1}", metaCls.Name, meta.Name);
- }
- return meta;
- }
-
- public static object __new__(CodeContext/*!*/ context, object cls, object o) {
- return DynamicHelpers.GetPythonType(o);
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
- public void __init__(object o) {
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static PythonTuple Get__bases__(CodeContext/*!*/ context, PythonType/*!*/ type) {
- return type.GetBasesTuple();
- }
-
- private PythonTuple GetBasesTuple() {
- object[] res = new object[BaseTypes.Count];
- IList<PythonType> bases = BaseTypes;
- for (int i = 0; i < bases.Count; i++) {
- PythonType baseType = bases[i];
-
- if (baseType.IsOldClass) {
- res[i] = baseType.OldClass;
- } else {
- res[i] = baseType;
- }
- }
-
- return PythonTuple.MakeTuple(res);
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static PythonType Get__base__(CodeContext/*!*/ context, PythonType/*!*/ type) {
- foreach (object typeObj in Get__bases__(context, type)) {
- PythonType pt = typeObj as PythonType;
- if (pt != null) {
- return pt;
- }
- }
- return null;
- }
-
- /// <summary>
- /// Used in copy_reg which is the only consumer of __flags__ in the standard library.
- ///
- /// Set if the type is user defined
- /// </summary>
- private const int TypeFlagHeapType = 1 << 9;
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static int Get__flags__(CodeContext/*!*/ context, PythonType/*!*/ type) {
- if (type.IsSystemType) {
- return 0;
- }
-
- return TypeFlagHeapType;
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Set__bases__(CodeContext/*!*/ context, PythonType/*!*/ type, object value) {
- // validate we got a tuple...
- PythonTuple t = value as PythonTuple;
- if (t == null) throw PythonOps.TypeError("expected tuple of types or old-classes, got '{0}'", PythonTypeOps.GetName(value));
-
- List<PythonType> ldt = new List<PythonType>();
-
- foreach (object o in t) {
- // gather all the type objects...
- PythonType adt = o as PythonType;
- if (adt == null) {
- OldClass oc = o as OldClass;
- if (oc == null) {
- throw PythonOps.TypeError("expected tuple of types, got '{0}'", PythonTypeOps.GetName(o));
- }
-
- adt = oc.TypeObject;
- }
-
- ldt.Add(adt);
- }
-
- // Ensure that we are not switching the CLI type
- Type newType = NewTypeMaker.GetNewType(type.Name, t);
- if (type.UnderlyingSystemType != newType)
- throw PythonOps.TypeErrorForIncompatibleObjectLayout("__bases__ assignment", type, newType);
-
- // set bases & the new resolution order
- List<PythonType> mro = CalculateMro(type, ldt);
-
- type.BaseTypes = ldt;
- type._resolutionOrder = mro;
- }
-
- private static List<PythonType> CalculateMro(PythonType type, IList<PythonType> ldt) {
- return Mro.Calculate(type, ldt);
- }
-
- private static bool TryReplaceExtensibleWithBase(Type curType, out Type newType) {
- if (curType.IsGenericType &&
- curType.GetGenericTypeDefinition() == typeof(Extensible<>)) {
- newType = curType.GetGenericArguments()[0];
- return true;
- }
- newType = null;
- return false;
- }
-
- public object __call__(CodeContext context, params object[] args) {
- return PythonTypeOps.CallParams(context, this, args);
- }
-
- public object __call__(CodeContext context, [ParamDictionary]IDictionary<string, object> kwArgs, params object[] args) {
- return PythonTypeOps.CallWorker(context, this, kwArgs, args);
- }
-
- public int __cmp__([NotNull]PythonType other) {
- if (other != this) {
- int res = Name.CompareTo(other.Name);
-
- if (res == 0) {
- long thisId = IdDispenser.GetId(this);
- long otherId = IdDispenser.GetId(other);
- if (thisId > otherId) {
- return 1;
- } else {
- return -1;
- }
- }
- return res;
- }
- return 0;
- }
-
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator >(PythonType self, PythonType other) {
- return self.__cmp__(other) > 0;
- }
-
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator <(PythonType self, PythonType other) {
- return self.__cmp__(other) < 0;
- }
-
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator >=(PythonType self, PythonType other) {
- return self.__cmp__(other) >= 0;
- }
-
- [Python3Warning("type inequality comparisons not supported in 3.x")]
- public static bool operator <=(PythonType self, PythonType other) {
- return self.__cmp__(other) <= 0;
- }
-
- public void __delattr__(CodeContext/*!*/ context, string name) {
- DeleteCustomMember(context, name);
- }
-
- [SlotField]
- public static PythonTypeSlot __dict__ = new PythonTypeDictSlot(_pythonTypeType);
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static object Get__doc__(CodeContext/*!*/ context, PythonType self) {
- PythonTypeSlot pts;
- object res;
- if (self.TryLookupSlot(context, "__doc__", out pts) &&
- pts.TryGetValue(context, null, self, out res)) {
- return res;
- } else if (self.IsSystemType) {
- return PythonTypeOps.GetDocumentation(self.UnderlyingSystemType);
- }
-
- return null;
- }
-
- public object __getattribute__(CodeContext/*!*/ context, string name) {
- object value;
- if (TryGetBoundCustomMember(context, name, out value)) {
- return value;
- }
-
- throw PythonOps.AttributeError("type object '{0}' has no attribute '{1}'", Name, name);
- }
-
- public PythonType this[params Type[] args] {
- get {
- if (UnderlyingSystemType == typeof(Array)) {
- if (args.Length == 1) {
- return DynamicHelpers.GetPythonTypeFromType(args[0].MakeArrayType());
- }
- throw PythonOps.TypeError("expected one argument to make array type, got {0}", args.Length);
- }
-
- if (!UnderlyingSystemType.IsGenericTypeDefinition) {
- throw new InvalidOperationException("MakeGenericType on non-generic type");
- }
-
- return DynamicHelpers.GetPythonTypeFromType(UnderlyingSystemType.MakeGenericType(args));
- }
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static object Get__module__(CodeContext/*!*/ context, PythonType self) {
- PythonTypeSlot pts;
- object res;
- if (self._dict != null &&
- self._dict.TryGetValue("__module__", out pts) &&
- pts.TryGetValue(context, self, DynamicHelpers.GetPythonType(self), out res)) {
- return res;
- }
- return PythonTypeOps.GetModuleName(context, self.UnderlyingSystemType);
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Set__module__(CodeContext/*!*/ context, PythonType self, object value) {
- if (self.IsSystemType) {
- throw PythonOps.TypeError("can't set {0}.__module__", self.Name);
- }
-
- Debug.Assert(self._dict != null);
- self._dict["__module__"] = new PythonTypeUserDescriptorSlot(value);
- self.UpdateVersion();
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Delete__module__(CodeContext/*!*/ context, PythonType self) {
- throw PythonOps.TypeError("can't delete {0}.__module__", self.Name);
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static PythonTuple Get__mro__(PythonType type) {
- return PythonTypeOps.MroToPython(type.ResolutionOrder);
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static string Get__name__(PythonType type) {
- return type.Name;
- }
-
- [SpecialName, PropertyMethod, WrapperDescriptor]
- public static void Set__name__(PythonType type, string name) {
- if (type.IsSystemType) {
- throw PythonOps.TypeError("can't set attributes of built-in/extension type '{0}'", type.Name);
- }
-
- type.Name = name;
- }
-
- public string/*!*/ __repr__(CodeContext/*!*/ context) {
- string name = Name;
-
- if (IsSystemType) {
- if (PythonTypeOps.IsRuntimeAssembly(UnderlyingSystemType.Assembly) || IsPythonType) {
- object module = Get__module__(context, this);
- if (!module.Equals("__builtin__")) {
- return string.Format("<type '{0}.{1}'>", module, Name);
- }
- }
- return string.Format("<type '{0}'>", Name);
- } else {
- PythonTypeSlot dts;
- string module = "unknown";
- object modObj;
- if (TryLookupSlot(context, "__module__", out dts) &&
- dts.TryGetValue(context, this, this, out modObj)) {
- module = modObj as string;
- }
- return string.Format("<class '{0}.{1}'>", module, name);
- }
- }
-
- internal string/*!*/ GetTypeDebuggerDisplay() {
- PythonTypeSlot dts;
- string module = "unknown";
- object modObj;
- if (TryLookupSlot(Context.SharedContext, "__module__", out dts) &&
- dts.TryGetValue(Context.SharedContext, this, this, out modObj)) {
- module = modObj as string;
- }
- return string.Format("{0}.{1} instance", module, Name);
- }
-
- public void __setattr__(CodeContext/*!*/ context, string name, object value) {
- SetCustomMember(context, name, value);
- }
-
- public List __subclasses__(CodeContext/*!*/ context) {
- List ret = new List();
- IList<WeakReference> subtypes = SubTypes;
-
- if (subtypes != null) {
- PythonContext pc = PythonContext.GetContext(context);
-
- foreach (WeakReference wr in subtypes) {
- if (wr.IsAlive) {
- PythonType pt = (PythonType)wr.Target;
-
- if (pt.PythonContext == null || pt.PythonContext == pc) {
- ret.AddNoLock(wr.Target);
- }
- }
- }
- }
-
- return ret;
- }
-
- public virtual List mro() {
- return new List(Get__mro__(this));
- }
-
- /// <summary>
- /// Returns true if the specified object is an instance of this type.
- /// </summary>
- public virtual bool __instancecheck__(object instance) {
- return SubclassImpl(DynamicHelpers.GetPythonType(instance));
- }
-
- public virtual bool __subclasscheck__(PythonType sub) {
- return SubclassImpl(sub);
- }
-
- private bool SubclassImpl(PythonType sub) {
- if (UnderlyingSystemType.IsInterface) {
- // interfaces aren't in bases, and therefore IsSubclassOf doesn't do this check.
- if (UnderlyingSystemType.IsAssignableFrom(sub.UnderlyingSystemType)) {
- return true;
- }
- }
-
- return sub.IsSubclassOf(this);
- }
-
- public virtual bool __subclasscheck__(OldClass sub) {
- return IsSubclassOf(sub.TypeObject);
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates")]
- public static implicit operator Type(PythonType self) {
- return self.UnderlyingSystemType;
- }
-
- public static implicit operator TypeTracker(PythonType self) {
- return ReflectionCache.GetTypeTracker(self.UnderlyingSystemType);
- }
-
- #endregion
-
- #region Internal API
-
- internal bool IsMixedNewStyleOldStyle() {
- if (!IsOldClass) {
- foreach (PythonType baseType in ResolutionOrder) {
- if (baseType.IsOldClass) {
- // mixed new-style/old-style class, we can't handle
- // __init__ in an old-style class yet (it doesn't show
- // up in a slot).
- return true;
- }
- }
- }
- return false;
- }
-
- internal int SlotCount {
- get {
- return _originalSlotCount;
- }
- }
-
- /// <summary>
- /// Gets the name of the dynamic type
- /// </summary>
- internal string Name {
- get {
- return _name;
- }
- set {
- _name = value;
- }
- }
-
- internal int Version {
- get {
- return _version;
- }
- }
-
- internal bool IsNull {
- get {
- return UnderlyingSystemType == typeof(DynamicNull);
- }
- }
-
- /// <summary>
- /// Gets the resolution order used for attribute lookup
- /// </summary>
- internal IList<PythonType> ResolutionOrder {
- get {
- return _resolutionOrder;
- }
- set {
- lock (SyncRoot) {
- _resolutionOrder = new List<PythonType>(value);
- }
- }
- }
-
- /// <summary>
- /// Gets the dynamic type that corresponds with the provided static type.
- ///
- /// Returns null if no type is available. TODO: In the future this will
- /// always return a PythonType created by the DLR.
- /// </summary>
- /// <param name="type"></param>
- /// <returns></returns>
- internal static PythonType/*!*/ GetPythonType(Type type) {
- object res;
-
- if (!_pythonTypes.TryGetValue(type, out res)) {
- lock (_pythonTypes) {
- if (!_pythonTypes.TryGetValue(type, out res)) {
- res = new PythonType(type);
-
- _pythonTypes.Add(type, res);
- }
- }
- }
-
- return (PythonType)res;
- }
-
- /// <summary>
- /// Sets the python type that corresponds with the provided static type.
- ///
- /// This is used for built-in types which have a metaclass. Currently
- /// only used by ctypes.
- /// </summary>
- internal static PythonType SetPythonType(Type type, PythonType pyType) {
- lock (_pythonTypes) {
- Debug.Assert(!_pythonTypes.Contains(type));
- Debug.Assert(pyType.GetType() != typeof(PythonType));
-
- _pythonTypes.Add(type, pyType);
- }
- return pyType;
- }
-
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context) {
- EnsureInstanceCtor();
-
- return _instanceCtor.CreateInstance(context);
- }
-
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context, object arg0) {
- EnsureInstanceCtor();
-
- return _instanceCtor.CreateInstance(context, arg0);
- }
-
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context, object arg0, object arg1) {
- EnsureInstanceCtor();
-
- return _instanceCtor.CreateInstance(context, arg0, arg1);
- }
-
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext/*!*/ context, object arg0, object arg1, object arg2) {
- EnsureInstanceCtor();
-
- return _instanceCtor.CreateInstance(context, arg0, arg1, arg2);
- }
-
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext context, params object[] args) {
- Assert.NotNull(args);
- EnsureInstanceCtor();
-
- // unpack args for common cases so we don't generate code to do it...
- switch (args.Length) {
- case 0: return _instanceCtor.CreateInstance(context);
- case 1: return _instanceCtor.CreateInstance(context, args[0]);
- case 2: return _instanceCtor.CreateInstance(context, args[0], args[1]);
- case 3: return _instanceCtor.CreateInstance(context, args[0], args[1], args[2]);
- default:
- return _instanceCtor.CreateInstance(context, args);
- }
- }
-
- /// <summary>
- /// Allocates the storage for the instance running the .NET constructor. This provides
- /// the creation functionality for __new__ implementations.
- /// </summary>
- internal object CreateInstance(CodeContext context, object[] args, string[] names) {
- Assert.NotNull(args, "args");
- Assert.NotNull(names, "names");
-
- EnsureInstanceCtor();
-
- return _instanceCtor.CreateInstance(context, args, names);
- }
-
- internal int Hash(object o) {
- EnsureHashSite();
-
- return _hashSite.Target(_hashSite, o);
- }
-
- internal bool TryGetLength(CodeContext context, object o, out int length) {
- CallSite<Func<CallSite, CodeContext, object, object>> lenSite;
- if (IsSystemType) {
- lenSite = PythonContext.GetContext(context).GetSiteCacheForSystemType(UnderlyingSystemType).GetLenSite(context);
- } else {
- lenSite = _siteCache.GetLenSite(context);
- }
-
- PythonTypeSlot lenSlot = _lenSlot;
- if (lenSlot == null && !PythonOps.TryResolveTypeSlot(context, this, "__len__", out lenSlot)) {
- length = 0;
- return false;
- }
-
- object func;
- if (!lenSlot.TryGetValue(context, o, this, out func)) {
- length = 0;
- return false;
- }
-
- object res = lenSite.Target(lenSite, context, func);
- if (!(res is int)) {
- throw PythonOps.ValueError("__len__ must return int");
- }
-
- length = (int)res;
- return true;
- }
-
- internal bool EqualRetBool(object self, object other) {
- if (_eqSite == null) {
- Interlocked.CompareExchange(
- ref _eqSite,
- Context.CreateComparisonSite(PythonOperationKind.Equal),
- null
- );
- }
-
- return _eqSite.Target(_eqSite, self, other);
- }
-
- internal int Compare(object self, object other) {
- if (_compareSite == null) {
- Interlocked.CompareExchange(
- ref _compareSite,
- Context.MakeSortCompareSite(),
- null
- );
- }
-
- return _compareSite.Target(_compareSite, self, other);
- }
-
- internal bool TryGetBoundAttr(CodeContext context, object o, string name, out object ret) {
- CallSite<Func<CallSite, object, CodeContext, object>> site;
- if (IsSystemType) {
- site = PythonContext.GetContext(context).GetSiteCacheForSystemType(UnderlyingSystemType).GetTryGetMemberSite(context, name);
- } else {
- site = _siteCache.GetTryGetMemberSite(context, name);
- }
-
- try {
- ret = site.Target(site, o, context);
- return ret != OperationFailed.Value;
- } catch (MissingMemberException) {
- ExceptionHelpers.DynamicStackFrames = null;
- ret = null;
- return false;
- }
- }
-
- internal CallSite<Func<CallSite, object, int>> HashSite {
- get {
- EnsureHashSite();
-
- return _hashSite;
- }
- }
-
- private void EnsureHashSite() {
- if(_hashSite == null) {
- Interlocked.CompareExchange(
- ref _hashSite,
- CallSite<Func<CallSite, object, int>>.Create(
- Context.Operation(
- PythonOperationKind.Hash
- )
- ),
- null
- );
- }
- }
-
- /// <summary>
- /// Gets the underlying system type that is backing this type. All instances of this
- /// type are an instance of the underlying system type.
- /// </summary>
- internal Type/*!*/ UnderlyingSystemType {
- get {
- return _underlyingSystemType;
- }
- }
-
- /// <summary>
- /// Gets the extension type for this type. The extension type provides
- /// a .NET type which can be inherited from to extend sealed classes
- /// or value types which Python allows inheritance from.
- /// </summary>
- internal Type/*!*/ ExtensionType {
- get {
- if (!_underlyingSystemType.IsEnum) {
- switch (Type.GetTypeCode(_underlyingSystemType)) {
- case TypeCode.String: return typeof(ExtensibleString);
- case TypeCode.Int32: return typeof(Extensible<int>);
- case TypeCode.Double: return typeof(Extensible<double>);
- case TypeCode.Object:
- if (_underlyingSystemType == typeof(BigInteger)) {
- return typeof(Extensible<BigInteger>);
- } else if (_underlyingSystemType == typeof(Complex)) {
- return typeof(ExtensibleComplex);
- }
- break;
- }
- }
- return _underlyingSystemType;
- }
- }
-
- /// <summary>
- /// Gets the base types from which this type inherits.
- /// </summary>
- internal IList<PythonType>/*!*/ BaseTypes {
- get {
- return _bases;
- }
- set {
- // validate input...
- foreach (PythonType pt in value) {
- if (pt == null) throw new ArgumentNullException("value", "a PythonType was null while assigning base classes");
- }
-
- // first update our sub-type list
-
- lock (_bases) {
- foreach (PythonType dt in _bases) {
- dt.RemoveSubType(this);
- }
-
- // set the new bases
- List<PythonType> newBases = new List<PythonType>(value);
-
- // add us as subtypes of our new bases
- foreach (PythonType dt in newBases) {
- dt.AddSubType(this);
- }
-
- UpdateVersion();
- _bases = newBases.ToArray();
- }
- }
- }
-
- /// <summary>
- /// Returns true if this type is a subclass of other
- /// </summary>
- internal bool IsSubclassOf(PythonType other) {
- // check for a type match
- if (other == this) {
- return true;
- }
-
- //Python doesn't have value types inheriting from ValueType, but we fake this for interop
- if (other.UnderlyingSystemType == typeof(ValueType) && UnderlyingSystemType.IsValueType) {
- return true;
- }
-
- return IsSubclassWorker(other);
- }
-
- private bool IsSubclassWorker(PythonType other) {
- for (int i = 0; i < _bases.Length; i++) {
- PythonType baseClass = _bases[i];
-
- if (baseClass == other || baseClass.IsSubclassWorker(other)) {
- return true;
- }
- }
-
- return false;
- }
-
- /// <summary>
- /// True if the type is a system type. A system type is a type which represents an
- /// underlying .NET type and not a subtype of one of these types.
- /// </summary>
- internal bool IsSystemType {
- get {
- return (_attrs & PythonTypeAttributes.SystemType) != 0;
- }
- set {
- if (value) _attrs |= PythonTypeAttributes.SystemType;
- else _attrs &= (~PythonTypeAttributes.SystemType);
- }
- }
-
- internal bool IsWeakReferencable {
- get {
- return (_attrs & PythonTypeAttributes.WeakReferencable) != 0;
- }
- set {
- if (value) _attrs |= PythonTypeAttributes.WeakReferencable;
- else _attrs &= (~PythonTypeAttributes.WeakReferencable);
- }
- }
-
- internal bool HasDictionary {
- get {
- return (_attrs & PythonTypeAttributes.HasDictionary) != 0;
- }
- set {
- if (value) _attrs |= PythonTypeAttributes.HasDictionary;
- else _attrs &= (~PythonTypeAttributes.HasDictionary);
- }
- }
-
- internal bool HasSystemCtor {
- get {
- return (_attrs & PythonTypeAttributes.SystemCtor) != 0;
- }
- }
-
- internal void SetConstructor(BuiltinFunction ctor) {
- _ctor = ctor;
- }
-
- internal bool IsPythonType {
- get {
- return (_attrs & PythonTypeAttributes.IsPythonType) != 0;
- }
- set {
- if (value) {
- _attrs |= PythonTypeAttributes.IsPythonType;
- } else {
- _attrs &= ~PythonTypeAttributes.IsPythonType;
- }
- }
- }
-
- internal OldClass OldClass {
- get {
- return _oldClass;
- }
- set {
- _oldClass = value;
- }
- }
-
- internal bool IsOldClass {
- get {
- return _oldClass != null;
- }
- }
-
- internal PythonContext PythonContext {
- get {
- return _pythonContext;
- }
- }
-
- internal PythonContext/*!*/ Context {
- get {
- return _pythonContext ?? DefaultContext.DefaultPythonContext;
- }
- }
-
- internal object SyncRoot {
- get {
- // TODO: This is un-ideal, we should lock on something private.
- return this;
- }
- }
-
- internal bool IsHiddenMember(string name) {
- PythonTypeSlot dummySlot;
- return !TryResolveSlot(DefaultContext.Default, name, out dummySlot) &&
- TryResolveSlot(DefaultContext.DefaultCLS, name, out dummySlot);
- }
-
- internal LateBoundInitBinder GetLateBoundInitBinder(CallSignature signature) {
- Debug.Assert(!IsSystemType); // going to hold onto a PythonContext, shouldn't ever be a system type
- Debug.Assert(_pythonContext != null);
-
- if (_lateBoundInitBinders == null) {
- Interlocked.CompareExchange(ref _lateBoundInitBinders, new Dictionary<CallSignature, LateBoundInitBinder>(), null);
- }
-
- lock(_lateBoundInitBinders) {
- LateBoundInitBinder res;
- if (!_lateBoundInitBinders.TryGetValue(signature, out res)) {
- _lateBoundInitBinders[signature] = res = new LateBoundInitBinder(this, signature);
- }
-
- return res;
- }
- }
-
- #endregion
-
- #region Type member access
-
- /// <summary>
- /// Looks up a slot on the dynamic type
- /// </summary>
- internal bool TryLookupSlot(CodeContext context, string name, out PythonTypeSlot slot) {
- if (IsSystemType) {
- return PythonBinder.GetBinder(context).TryLookupSlot(context, this, name, out slot);
- }
-
- return _dict.TryGetValue(name, out slot);
- }
-
- /// <summary>
- /// Searches the resolution order for a slot matching by name
- /// </summary>
- internal bool TryResolveSlot(CodeContext context, string name, out PythonTypeSlot slot) {
- for (int i = 0; i < _resolutionOrder.Count; i++) {
- PythonType dt = _resolutionOrder[i];
-
- // don't look at interfaces - users can inherit from them, but we resolve members
- // via methods implemented on types and defined by Python.
- if (dt.IsSystemType && !dt.UnderlyingSystemType.IsInterface) {
- return PythonBinder.GetBinder(context).TryResolveSlot(context, dt, this, name, out slot);
- }
-
- if (dt.TryLookupSlot(context, name, out slot)) {
- return true;
- }
- }
-
- if (UnderlyingSystemType.IsInterface) {
- return TypeCache.Object.TryResolveSlot(context, name, out slot);
- }
-
-
- slot = null;
- return false;
- }
-
- /// <summary>
- /// Searches the resolution order for a slot matching by name.
- ///
- /// Includes searching for methods in old-style classes
- /// </summary>
- internal bool TryResolveMixedSlot(CodeContext context, string name, out PythonTypeSlot slot) {
- for (int i = 0; i < _resolutionOrder.Count; i++) {
- PythonType dt = _resolutionOrder[i];
-
- if (dt.TryLookupSlot(context, name, out slot)) {
- return true;
- }
-
- if (dt.OldClass != null) {
- object ret;
- if (dt.OldClass.TryLookupSlot(name, out ret)) {
- slot = ToTypeSlot(ret);
- return true;
- }
- }
- }
-
- slot = null;
- return false;
- }
-
- /// <summary>
- /// Internal helper to add a new slot to the type
- /// </summary>
- /// <param name="name"></param>
- /// <param name="slot"></param>
- internal void AddSlot(string name, PythonTypeSlot slot) {
- Debug.Assert(!IsSystemType);
-
- _dict[name] = slot;
- if (name == "__new__") {
- _objectNew = null;
- ClearObjectNewInSubclasses(this);
- } else if (name == "__init__") {
- _objectInit = null;
- ClearObjectInitInSubclasses(this);
- }
- }
-
- private void ClearObjectNewInSubclasses(PythonType pt) {
- lock (_subtypesLock) {
- if (pt._subtypes != null) {
- foreach (WeakReference wr in pt._subtypes) {
- PythonType type = wr.Target as PythonType;
- if (type != null) {
- type._objectNew = null;
-
- ClearObjectNewInSubclasses(type);
- }
- }
- }
- }
- }
-
- private void ClearObjectInitInSubclasses(PythonType pt) {
- lock (_subtypesLock) {
- if (pt._subtypes != null) {
- foreach (WeakReference wr in pt._subtypes) {
- PythonType type = wr.Target as PythonType;
- if (type != null) {
- type._objectInit = null;
-
- ClearObjectInitInSubclasses(type);
- }
- }
- }
- }
- }
-
- internal bool TryGetCustomSetAttr(CodeContext context, out PythonTypeSlot pts) {
- PythonContext pc = PythonContext.GetContext(context);
- return pc.Binder.TryResolveSlot(
- context,
- DynamicHelpers.GetPythonType(this),
- this,
- "__setattr__",
- out pts) &&
- pts is BuiltinMethodDescriptor &&
- ((BuiltinMethodDescriptor)pts).DeclaringType != typeof(PythonType);
- }
-
- internal void SetCustomMember(CodeContext/*!*/ context, string name, object value) {
- Debug.Assert(context != null);
-
- PythonTypeSlot dts;
- if (TryResolveSlot(context, name, out dts)) {
- if (dts.TrySetValue(context, null, this, value))
- return;
- }
-
- if (PythonType._pythonTypeType.TryResolveSlot(context, name, out dts)) {
- if (dts.TrySetValue(context, this, PythonType._pythonTypeType, value))
- return;
- }
-
- if (IsSystemType) {
- throw new MissingMemberException(String.Format("'{0}' object has no attribute '{1}'", Name, name));
- }
-
- PythonTypeSlot curSlot;
- if (!(value is PythonTypeSlot) && _dict.TryGetValue(name, out curSlot) && curSlot is PythonTypeUserDescriptorSlot) {
- ((PythonTypeUserDescriptorSlot)curSlot).Value = value;
- } else {
- AddSlot(name, ToTypeSlot(value));
- UpdateVersion();
- }
- }
-
- internal static PythonTypeSlot ToTypeSlot(object value) {
- PythonTypeSlot pts = value as PythonTypeSlot;
- if (pts != null) {
- return pts;
- }
-
- // We could do more checks for things which aren't descriptors
- if (value != null) {
- return new PythonTypeUserDescriptorSlot(value);
- …
Large files files are truncated, but you can click here to view the full file