using System;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace agree
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// ConstraintRef is a value type. It consists of:
/// - reference to a top-level TFS which provides access to edges
/// - a current 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.
/// - a selected feature index, relative to the TypeMgr of the TFS
///
/// 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 is not available given only an Edge.
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public partial struct ConstraintRef
{
public static readonly ConstraintRef[] NoneBelow = new ConstraintRef[0];
public ConstraintRef(Tfs tfs, Edge host, int i_feat)
{
this.Host = host;
this.i_feat = i_feat;
this.tfs = tfs;
}
public ConstraintRef(Tfs host)
{
this.Host = host.Edge;
this.tfs = host;
this.i_feat = -1;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Tfs tfs;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// The hosting edge. For 'read' performance, the field itself is exposed, but do not 'write' this field; use
/// SetHost() or SetHostType() instead.
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Edge Host;
public void SetHostType(Type new_type)
{
if (HostType != new_type)
{
Host = ((MarkingTfs)tfs).CreateRecycledEdge(new_type, Host.Mark, Host.IsCoreferenced);
if (!HostType.HasFeature(i_feat))
i_feat = -1;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// The selected feature is determined by a non-null ConstraintPool
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public int i_feat;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public FeatureInfo FeatureInfo { get { return tfs.tm.feat_arr[i_feat]; } }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public String Feature { get { return tfs.tm.feat_arr[i_feat].feature; } }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Type HostType { get { return tfs.tm.GetEdgeType(Host.FlagsId); } }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public FeatMark FeatMark { get { return new FeatMark(i_feat, Host.Mark); } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Stays in the same Tray
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void SwitchToFeature(int i_feat)
{
if (this.i_feat==-1 || this.i_feat != i_feat)
{
if (i_feat == -1 || !HostType.HasFeature(i_feat))
throw new Exception();
this.i_feat = i_feat;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
/// <remarks>
/// value type semantics are weird for 'set' as a property so we use a method instead
/// </remarks>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Edge Constraint
{
get { return tfs.GetEdge(i_feat, Host.Mark); }
}
public void SetConstraint(Edge e)
{
tfs.SetEdge(i_feat, Host.Mark, e);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Type ConstraintType
{
get
{
Edge e;
if (!tfs.TryGetEdge(i_feat, Host.Mark, out e))
return tfs.tm.TopType;
return tfs.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 TFS
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public ConstraintRef NextConstraint(int i_nf)
{
return new ConstraintRef(tfs, tfs.GetEdge(this.i_feat, Host.Mark), i_nf);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Unify types, only used by TdlNavigator
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool UnifyInConstraintType(Type t)
{
Debug.Assert(i_feat != -1, "UnifyInType: Edge has no feature selected.");
int tid = ConstraintType.m_id;
int glb_id = t.tm.GetGlbCheckTopAndIdentity(tid, t.m_id);
if (glb_id == -1)
return false;
if (glb_id != tid)
{
Edge old_edge = tfs.GetEdge(i_feat, Host.Mark);
tfs.SetEdge(i_feat, Host.Mark, ((MarkingTfs)tfs).CreateRecycledEdge(t.tm.type_arr[glb_id], old_edge.Mark, old_edge.IsCoreferenced));
}
return true;
}
};
}