Beispiel #1
0
        private static Type GetBaseTypeFromUserType(PythonType curBasePythonType, IList <Type> baseInterfaces, Type curTypeToExtend)
        {
            Queue <PythonType> processing = new Queue <PythonType>();

            processing.Enqueue(curBasePythonType);

            do
            {
                PythonType walking = processing.Dequeue();
                foreach (PythonType dt in walking.BaseTypes)
                {
                    if (dt.ExtensionType == curTypeToExtend || curTypeToExtend.IsSubclassOf(dt.ExtensionType))
                    {
                        continue;
                    }

                    if (dt.ExtensionType.IsInterface)
                    {
                        baseInterfaces.Add(dt.ExtensionType);
                    }
                    else if (NewTypeMaker.IsInstanceType(dt.ExtensionType))
                    {
                        processing.Enqueue(dt);
                    }
                    else if (!dt.IsOldClass)
                    {
                        curTypeToExtend = null;
                        break;
                    }
                }
            } while (processing.Count > 0);
            return(curTypeToExtend);
        }
Beispiel #2
0
        public override Type GetTypesToExtend(out IList <Type> interfacesToExtend)
        {
            interfacesToExtend = new List <Type>();
            foreach (object b in bases)
            {
                if (b is OldClass)
                {
                    continue;
                }

                PythonType   baseType = b as PythonType;
                IList <Type> baseTypeInterfaces;
                baseType.GetTypesToExtend(out baseTypeInterfaces);
                foreach (Type baseTypeInterface in baseTypeInterfaces)
                {
                    interfacesToExtend.Add(baseTypeInterface);
                }
            }
            // We dont use type.GetInterfaces() as it contains all the interfaces that are added by NewTypeMaker,
            // as well as all the interfaces implemented by type.BaseType. Instead, we only want the new set of
            // interfaces that need to be implemented by the new instance type.
            Debug.Assert(interfacesToExtend.Count < type.GetInterfaces().Length);

            // "type" is the instance type used for instances of this type. This will be a type created by NewTypeMaker.
            Debug.Assert(NewTypeMaker.IsInstanceType(type));
            // Its BaseType will the CLI type that needs to be inherited by instance types used by other UserTypes inheriting
            // from the current UserType. For pure Python types, this will be System.Object.
            Debug.Assert(!NewTypeMaker.IsInstanceType(type.BaseType));

            return(type.BaseType);
        }
Beispiel #3
0
        /// <summary>
        /// "bases" contains a set of PythonTypes. These can include types defined in Python (say cpy1, cpy2),
        /// CLI types (say cCLI1, cCLI2), and CLI interfaces (say iCLI1, iCLI2). Here are some
        /// examples of how this works:
        ///
        /// (bases)                      => baseType,        {interfaceTypes}
        ///
        /// (cpy1)                       => System.Object,   {}
        /// (cpy1, cpy2)                 => System.Object,   {}
        /// (cpy1, cCLI1, iCLI1, iCLI2)  => cCLI1,           {iCLI1, iCLI2}
        /// [some type that satisfies the line above] =>
        ///                                 cCLI1,           {iCLI1, iCLI2}
        /// (cCLI1, cCLI2)               => error
        /// </summary>
        public static NewTypeInfo GetTypeInfo(string typeName, PythonTuple bases)
        {
            List <Type> interfaceTypes = new List <Type>();
            Type        baseCLIType    = typeof(object); // Pure Python object instances inherit from System.Object
            PythonType  basePythonType = null;

            foreach (PythonType curBasePythonType in GetPythonTypes(typeName, bases))
            {
                // discover the initial base/interfaces
                IList <Type> baseInterfaces  = ReflectionUtils.EmptyTypes;
                Type         curTypeToExtend = curBasePythonType.ExtensionType;

                if (curBasePythonType.ExtensionType.IsInterface)
                {
                    baseInterfaces  = new Type[] { curTypeToExtend };
                    curTypeToExtend = typeof(object);
                }
                else if (NewTypeMaker.IsInstanceType(curTypeToExtend))
                {
                    baseInterfaces  = new List <Type>();
                    curTypeToExtend = GetBaseTypeFromUserType(curBasePythonType, baseInterfaces, curTypeToExtend.BaseType);
                }

                if (curTypeToExtend == null || typeof(BuiltinFunction).IsAssignableFrom(curTypeToExtend) || typeof(PythonFunction).IsAssignableFrom(curTypeToExtend))
                {
                    throw PythonOps.TypeError(typeName + ": {0} is not an acceptable base type", curBasePythonType.Name);
                }
                if (curTypeToExtend.ContainsGenericParameters)
                {
                    throw PythonOps.TypeError(typeName + ": cannot inhert from open generic instantiation {0}. Only closed instantiations are supported.", curBasePythonType);
                }

                foreach (Type interfaceType in baseInterfaces)
                {
                    if (interfaceType.ContainsGenericParameters)
                    {
                        throw PythonOps.TypeError(typeName + ": cannot inhert from open generic instantiation {0}. Only closed instantiations are supported.", interfaceType);
                    }

                    // collecting all the interfaces because we override them all.
                    interfaceTypes.Add(interfaceType);
                }

                // if we're not extending something already in our existing base classes type hierarchy
                // then we better be in some esoteric __slots__ situation
                if (!baseCLIType.IsSubclassOf(curTypeToExtend))
                {
                    if (baseCLIType != typeof(object) && baseCLIType != curTypeToExtend &&
                        (!baseCLIType.IsDefined(typeof(DynamicBaseTypeAttribute), false) && !curTypeToExtend.IsSubclassOf(baseCLIType)))
                    {
                        throw PythonOps.TypeError(
                                  typeName + ": can only extend one CLI or builtin type, not both {0} (for {1}) and {2} (for {3})",
                                  baseCLIType.FullName,
                                  basePythonType,
                                  curTypeToExtend.FullName,
                                  curBasePythonType);
                    }

                    // we have a new base type
                    baseCLIType    = curTypeToExtend;
                    basePythonType = curBasePythonType;
                }
            }
            return(new NewTypeInfo(baseCLIType, interfaceTypes.Count == 0 ? ReflectionUtils.EmptyTypes : interfaceTypes.ToArray()));
        }