Example #1
0
        /// <summary>
        /// </summary>
        public static Tuple Calculate(IPythonType startingType, Tuple bases, bool forceNewStyle)
        {
            if (bases.ContainsValue(startingType)) {
                throw Ops.TypeError("a __bases__ item causes an inheritance cycle");
            }

            List<IPythonType> mro = new List<IPythonType>();
            mro.Add(startingType);

            if (bases.Count != 0) {
                List<List<IPythonType>> mroList = new List<List<IPythonType>>();
                // build up the list - it contains the MRO of all our
                // bases as well as the bases themselves in the order in
                // which they appear.
                int oldSytleCount = 0;
                foreach (IPythonType type in bases) {
                    if (!(type is DynamicType))
                        oldSytleCount++;
                }

                foreach (IPythonType type in bases) {
                    DynamicType dt = type as DynamicType;
                    if (dt != null) {
                        mroList.Add(TupleToList(dt.MethodResolutionOrder));
                    } else if (oldSytleCount == 1 && !forceNewStyle) {
                        mroList.Add(GetOldStyleMro(type));
                    } else {
                        mroList.Add(GetNewStyleMro(type));
                    }
                }

                mroList.Add(TupleToList(bases));

                int lastRemove = -1;
                for (; ; ) {
                    bool removed = false, sawNonZero = false;
                    // now that we have our list, look for good heads
                    for (int i = 0; i < mroList.Count; i++) {
                        if (mroList[i].Count == 0) continue;    // we've removed everything from this list.

                        sawNonZero = true;
                        IPythonType head = mroList[i][0];
                        // see if we're in the tail of any other lists...
                        bool inTail = false;
                        for (int j = 0; j < mroList.Count; j++) {
                            if (mroList[j].Count != 0 && !mroList[j][0].Equals(head) && mroList[j].Contains(head)) {
                                inTail = true;
                                break;
                            }
                        }

                        if (!inTail) {
                            lastRemove = i;
                            if (mro.Contains(head)) {
                                throw Ops.TypeError("a __bases__ item causes an inheritance cycle");
                            }
                            // add it to the linearization, and remove
                            // it from our lists
                            mro.Add(head);

                            for (int j = 0; j < mroList.Count; j++) {
                                mroList[j].Remove(head);
                            }
                            removed = true;
                            break;
                        }
                    }

                    if (!sawNonZero) break;

                    if (!removed) {
                        // we've iterated through the list once w/o removing anything
                        throw Ops.TypeError("invalid order for base classes: {0} {1}",
                            mroList[0][0],
                            mroList[1][0]);
                    }
                }
            }

            return new Tuple(mro);
        }