using System; using System.Text; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Doesn't carry the in-mark /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public struct PoolEdge { public PoolEdge(ConstraintPool cp, Edge edge) { this.Pool = cp; this.Edge = edge; } public ConstraintPool Pool; public Edge Edge; public override string ToString() { return String.Format(" {0} {1}", Pool.Feature.ToUpper(), Edge.ToString()); } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// ConstraintRef is a value type. It consists of: /// - a ConstraintPool which represents the distinct repository for all uses of some single feature that is appropriate /// for the hosting type; /// - a host edge, which consists of a 'hosting' Type (which may or may not be the same as the introducing type for the /// constraint pool's feature), and an in-mark that selects an onwards edge in that constraint pool. /// /// This structure is therefore able to indicate a specific FEATURE-type pair within a TFS, while maintaining the /// critically-important ability to alter that type assignment, which would normally be lost in a CLR value type. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial struct ConstraintRef : IEquatable<ConstraintRef> { public ConstraintRef(Edge host, ConstraintPool cp) { this.Host = host; this.Pool = cp; } public ConstraintRef(TfsEdge host) { this.Host = host.Edge; this.Pool = host.Tray.UnknownPool; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// The hosting edge. For 'read' performance, the field itself is exposed, but do not 'write' this field; use /// SetHost() or SetHostType() instead. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public Edge Host; public void SetHostType(Type new_type) { if (HostType != new_type) { Host = Pool.tr.CreateRecycledEdge(new_type, Host.Mark, Host.IsCoreferenced); if (!HostType.HasFeature(Pool.i_feat)) Pool = Pool.tr.UnknownPool; } } public Type HostType { get { return Pool.tm.GetEdgeType(Host.FlagsId); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public PoolMark PoolMark { get { return new PoolMark(Pool, Host.Mark); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// The selected feature is determined by a non-null ConstraintPool /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public ConstraintPool Pool; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public String Feature { get { return Pool.Feature; } } public int FeatureIndex { get { return HostType.mgr.GetFeatureIndex(Pool.Feature); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Stays in the same Tray /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public void SwitchToFeature(int i_feat) { if (Pool is UnknownPoolClass || Pool.i_feat != i_feat) { if (i_feat == -1 || !HostType.HasFeature(i_feat)) throw new Exception(); Pool = Pool.tr.Pools[i_feat]; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /// <remarks> /// value type semantics are weird for 'set' as a property so we use a method instead /// </remarks> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public Edge Constraint { get { return Pool.GetEdge(Host.Mark); } } public void SetConstraint(Edge e) { Pool.SetEdge(Host.Mark, e); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerBrowsable(DebuggerBrowsableState.Never)] public Type ConstraintType { get { Edge e; TypeMgr tm = Pool.tm; if (!Pool.TryGetEdge(Host.Mark, out e)) return tm.TopType; return tm.GetEdgeType(e.FlagsId); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// returns 'true' even if coreferenced /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool ConstraintTypeIsTop { get { return ConstraintType.IsTop; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] public bool ConstraintTypeIsBare { get { return ConstraintType.IsBare; } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// always stays in the same Tray /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public ConstraintRef NextConstraint(int i_feat) { return new ConstraintRef(Pool.GetEdge(Host.Mark), Pool.tr.Pools[i_feat]); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Unify types, only used by TdlNavigator /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool UnifyInConstraintType(Type t) { Debug.Assert(!(Pool is UnknownPoolClass), "UnifyInType: Edge has no feature selected."); int tid = ConstraintType.m_id; int glb_id = t.mgr.GetGlbCheckTopAndIdentity(tid, t.m_id); if (glb_id == -1) return false; if (glb_id != tid) { Edge old_edge = Pool.GetEdge(Host.Mark); Pool.SetEdge(Host.Mark, Pool.tr.CreateRecycledEdge(t.mgr.type_arr[glb_id], old_edge.Mark, old_edge.IsCoreferenced)); } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool Equals(ConstraintRef other) { return Host.Mark == other.Host.Mark && Pool == other.Pool && Host.FlagsId == other.Host.FlagsId; } public static bool operator ==(ConstraintRef x, ConstraintRef y) { return x.Equals(y); } public static bool operator !=(ConstraintRef x, ConstraintRef y) { return !x.Equals(y); } public override bool Equals(object obj) { throw new NotImplementedException(); } public override int GetHashCode() { return (int)Host.FlagsId ^ Host.Mark ^ Pool.i_feat; } }; }