/// <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); }