using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using miew.Concurrency;
using miew.Debugging;
namespace agree
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Type in the type hierarchy. This hierarchy is a fully-connected directed-acyclic graph (DAG) where each type
/// supports zero or more features that may be arbitrarily constrained to be any type in the hierarchy.
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public sealed partial class Type : GlbDag
{
public Type(TypeMgr tm, String name, List<BaseFeatConstraint> bfc)
: base(tm, name, bfc)
{
}
public static Type MakeTopType(TypeMgr tm, String name)
{
Type t = new Type(tm, name, null);
t.m_id = TypeMgr.TopId;
t._definition = tm.TopTfs;
t._expanded = tm.TopTfs;
return t;
}
public bool IsTop { get { return this == tm.TopType; } }
/// <summary>
/// if a type has authored constraints then, when it is the result of a unification meet
/// and is not the same as either type, it must go through the extra step of
/// being made well-formed. It is not sufficient to check HasLocalFeatures because
/// a type can further constraint features that it did not introduce
/// </summary>
public bool HasConstraints { get { return (m_flags & Flags.HasConstraints) > 0; } }
/// <summary>
/// 'Atomic' types have no appropriate features in their inclusive subgraph (Copestake 2001 p.68)
/// We term featureless types "bare." For example, *top* is not atomic, despite being bare.
/// </summary>
public bool IsAtomic { get { return (m_flags & Flags.Atomic) > 0; } }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
HashSet<int> _feat_gather = null;
public FeatureConfig fc = FeatureConfig.Empty;
public override Type InstanceType { get { return this; } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void AddLocalFeature(int i_feat)
{
if ((m_flags & Flags.LoadedNonLocalFeatures) > 0)
throw new Exception("Cannot add local features because parent features have already been calculated.");
(_feat_gather = _feat_gather ?? new HashSet<int>()).Add(i_feat);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Internal use only. Implements lazy loading of parent features.
/// Assumes local features have already been added to m_appropriate_features for the parent types, so this should
/// be called for all types according to topological order.
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
internal void AddNonLocalFeatures()
{
if ((m_flags & Flags.HasAnyFeatures) > 0)
{
foreach (Type par in Parents)
{
if ((par.m_flags & Flags.LoadedNonLocalFeatures) == 0)
throw new Exception("Incorrect topological order while calculating inherited features.");
if (par.fc.Count > 0)
{
_feat_gather = _feat_gather ?? new HashSet<int>();
_feat_gather.UnionWith(par.fc);
}
}
/// Set the order for which features of this type are enumerated.
/// Observation: unification failures tend to happen in more common types, as opposed to more obscure ones.
/// Reverse this ordering and you'll see.
/// We use the following order to unify the features of a type, i.e. according to the topological order of
/// their introducing type.
fc = tm.fcm.Get(this, _feat_gather);
_feat_gather = null;
}
m_flags |= Flags.LoadedNonLocalFeatures;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <returns>
/// 'false' if the specified feature does not exist or is not appropriate for this type.
/// </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool HasFeature(int i_feat)
{
int[] arr = fc.rg_fix;
for (int i = 0; i < arr.Length; i++)
if (arr[i] == i_feat)
return true;
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public override Tfs EnsureExpanded(out bool f_did)
{
f_did = false;
Tfs _tmp, _new;
if ((_tmp = _expanded) != null)
return _tmp;
if (!HasAnyFeatures)
return _expanded = Definition;
Stopwatch stopw = Stopwatch.StartNew();
TargetTfs tt = Unification.ExpandType(this);
if (tt == null)
throw new TfsException("Error expanding type '{0}': could not unify with its constraint or parents.", this.Name);
if ((_tmp = _expanded) != null)
return _tmp;
int ec = tt.EdgeCount;
if (ec == 0)
_new = new BareTfs(tt.Type);
//else if (ec < 12)
// _new = new TinyTfs(tt);
else
_new = tt.ToArrayTfs();
_new.Name = Name + " - Expanded";
if ((_tmp = _expanded) != null)
return _tmp;
Interlocked.Add(ref tm.ms_expand, (int)stopw.ElapsedMilliseconds);
if ((_tmp = Interlocked.CompareExchange(ref _expanded, _new, null)) != null)
return _tmp;
f_did = true;
return _new;
}
};
}