using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using miew.BitArray; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public abstract partial class GlbDag : Instance { public GlbDag(TypeMgr mgr, String name, List<BaseFeatConstraint> bfc) : base(mgr, name, bfc) { } public int m_id; public ushort m_level; public BitArr m_code; [DebuggerBrowsable(DebuggerBrowsableState.Never)] protected HashSet<Type> i_parents = new HashSet<Type>(); [DebuggerBrowsable(DebuggerBrowsableState.Never)] protected HashSet<Type> i_children = new HashSet<Type>(); public ushort FindLevel() { if (m_level == 0 && this != tm.TopType) { if (i_children.Count == 0) m_flags |= Flags.Leaf; m_level = (ushort)(i_parents.Max(p => p.FindLevel()) + 1); } return m_level; } public int ChildCount { get { return i_children.Count; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool IsGlb { get { return (m_flags & Flags.GlbType) > 0; } } /// <summary> /// leaf types have no children. They may have appropriate features /// </summary> public bool IsLeaf { get { return (m_flags & Flags.Leaf) > 0; } } public void AddIParent(Type p) { i_parents.Add(p); p.i_children.Add((Type)this); } public void RemoveIParent(Type p) { p.i_children.Remove((Type)this); i_parents.Remove(p); } public void AddIChild(Type c) { if (c == this) return; i_children.Add(c); c.i_parents.Add((Type)this); } public void RemoveIChild(Type c) { c.i_parents.Remove((Type)this); i_children.Remove(c); } /// <summary> /// Immediate parents only. Does not include this node /// </summary> public HashSet<Type> Parents { get { return i_parents; } } /// <summary> /// Immediate children only. Does not include this node /// </summary> public HashSet<Type> Children { get { return i_children; } } /// <summary> /// does not include this node /// </summary> public HashSet<Type> AllAncestors { get { HashSet<Type> l = AllAncestorsInclusive; l.Remove((Type)this); return l; } } public HashSet<Type> AllAncestorsInclusive { get { HashSet<Type> l = new HashSet<Type>(); Action<Type> f = null; f = (n) => { foreach (Type t in n.i_parents) if (!l.Contains(t)) f(t); l.Add(n); }; f((Type)this); return l; } } /// <summary> /// does not include this node /// </summary> public HashSet<Type> AllDescendants { get { HashSet<Type> l = AllDescendantsInclusive; l.Remove((Type)this); return l; } } public HashSet<Type> AllDescendantsInclusive { get { HashSet<Type> l = new HashSet<Type>(); Action<Type> f = null; f = (n) => { foreach (Type t in n.i_children) if (!l.Contains(t)) f(t); l.Add(n); }; f((Type)this); return l; } } public void SetHasAnyFeaturesFlagBelow() { m_flags |= Flags.HasAnyFeatures; foreach (Type c in this.i_children) { if ((c.m_flags & Flags.HasAnyFeatures) == 0) c.SetHasAnyFeaturesFlagBelow(); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Proper subtype relationship, ⊐, as in: t ⊐ *top* /// Returns 'true' if this node is in the proper child graph of the specified argument. /// Complementary to IsSupertypeOf. /// This is used by the graph closure, so it does not use the GLB cache, and must not be made to do so. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool IsSubtypeOf(Type tt_other) { return (tt_other == this) ? false : m_code.AndGivesExact(tt_other.m_code); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Proper subsumption, ⊏, as in: top.Subsumes(everything-else). /// Returns 'true' if this node is properly in the parent graph of the specified argument. /// Complementary to IsSubtypeOf. /// This is used by the graph closure, so it does not use the GLB cache, and must not be made to do so. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool IsSupertypeOf(Type tt_other) { return (tt_other == this) ? false : tt_other.m_code.AndGivesExact(m_code); } }; }