using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using miew.Tally;
using miew.Debugging;
using miew.Enumerable;
using miew.String;
using miew.Tokenization;
namespace agree
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public sealed partial class TargetTfs : BootstrapTfs//, ITargetTfs
{
public TargetTfs(TypeMgr tm, int c_edge_hint)
: base(tm, c_edge_hint)
{
c_corefs = 0;
}
public Dictionary<Int64, Unification.UnifCoref> corefs = null;
public int c_corefs = 0;
#if true
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Prune a sub-graph, and then remove any unused coreferences (and unmark the edge coreference bit) which
/// have only a single use remaining.
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public bool _prune_below(int i_feat, int m)
{
Edge e;
if (!TryGetEdge(i_feat, m, out e))
return false;
int c_reentrancies = 0;
Unification.UnifCoref uc = null;
if (e.FlagsId < 0)
{
/// find coreference for this edge
corefs.TryGetValue(((long)id << 32) | (uint)e.Mark, out uc);
while (uc.f_redirect)
uc = uc.next;
/// if we are pruning the opportunistic reentrancy hint, then clear it
if (uc.single_fm.i_feat == i_feat && uc.single_fm.m == m)
uc.single_fm = default(FeatMark);
c_reentrancies = --uc.c_fm;
e = uc.e_cur;
}
/// only remove *below* a coreferenced edge if it has no reentrancies remaining. This allows sub-graphs to
/// be pruned without disturbing the coreferenced portions that are still accessible from without.
if (c_reentrancies == 0 && (e.FlagsId & agree.Edge.Flag.EtmNonBareType) != 0)
foreach (int fix in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
_prune_below(fix, e.Mark);
/// remove the edge
if (!RemoveEdge(i_feat, m))
Debug.Assert(false);
/// all done if not coreferenced, or if additional reentrancies still point to this edge.
if (uc == null || c_reentrancies > 1)
return true;
/// 0 or 1 reentrancies remain. we will decrement the coreference count at the end of this function.
if (c_reentrancies == 1)
{
/// if there's were 2 reentrancies and now there's just 1 remaining, we're retaining *this* edge,
/// so clear its coreference bit, as stored by the *other* reentrancy, and discard the equivalence
/// class. We make these adjustments now, because that other edge might not be getting pruned,
/// so we might never encounter it. First, find out if the opportunistic hint is any good.
FeatMark fm = uc.single_fm;
if (fm.m == 0)
{
/// hint is no good; we must find the other reentrancy by exhaustive search
ulong ul = d.First(kvp =>
{
if (kvp.Value.FlagsId >= 0)
return false;
var ux = corefs[((long)id << 32) | (uint)kvp.Value.Mark];
while (ux.f_redirect)
ux = ux.next;
return ux == uc;
}).Key;
fm = new FeatMark((int)(ul >> 32), (int)ul);
}
Debug.Assert(ContainsFeatMark(fm.i_feat, fm.m));
uc.c_fm = 0;
#if DEBUG
uc.single_fm = default(FeatMark);
#endif
/// clear coreference bit (or remove) in the other reentrancy.
Edge.Flag nf = e.FlagsId & ~Edge.Flag.Coreference;
if (nf == 0)
RemoveEdge(fm.i_feat, fm.m);
else
SetEdge(fm.i_feat, fm.m, new Edge(nf, (nf & Edge.Flag.EtmNonBareType) == 0 ? 0 : e.Mark));
}
c_corefs--;
return true;
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public Tfs ToArrayTfs()
{
#if DEBUG
CheckCoreferences();
#endif
ArrayTfs tfs = new ArrayTfs(tm.da, this, null);
//MarkingArrayTfs tfs = new MarkingArrayTfs(tm, this.Edge, d, id, corefs, ref c_corefs);
d = null;
tfs.Name = this.Name;
return tfs;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public MotherDaughterTfs ToMotherDaughterTfs(int[] rg_feat_delete)
{
#if DEBUG
CheckCoreferences();
#endif
MotherDaughterTfs tfs = new MotherDaughterTfs(tm.da, this, rg_feat_delete);
d = null;
tfs.Name = this.Name;
return tfs;
}
#if DEBUG
public override void CheckCoreferences()
{
//if (d == null)
//{
// base.CheckCoreferences();
// return;
//}
///// walking method:
//var walk = GetReentrancies(Edge)
// .Select(kvp => new KeyValuePair<Edge, ReentrancyFinder.Entry>(corefs[((long)id << 32) | (uint)kvp.Key.Mark].LoopMaster.e_cur, kvp.Value)) /// apply coref info
// .GroupBy(kvp => kvp.Key)
// .ToDictionary(
// grp => grp.Key,
// grp => grp.SelectMany(ue => ue.Value).Select(cref => cref.FeatMark).ToHashSet().Count); /// ignore types since they might not be updated yet
//if (walk.Count == 0)
// return;
///// table scan method:
//var table = d.Values
// .Where(e => e.FlagsId < 0)
// .Select(e => corefs[((long)id << 32) | (uint)e.Mark].LoopMaster.e_cur) /// apply coref info
// .GroupBy(e => e.Mark)
// .ToDictionary(grp => grp.First(), grp => grp.Count());
//if (walk.Count > table.Count)
//{
// var ex = walk.Keys.Except(table.Keys).ToArray();
// if (Debugger.IsAttached)
// Debugger.Break();
// else
// throw new Exception();
//}
//if (table.Count > walk.Count)
//{
// var ex = table.Keys.Except(walk.Keys).ToArray();
// if (Debugger.IsAttached)
// Debugger.Break();
// else
// throw new Exception();
//}
//var dqe = table.Where(kvp => walk[kvp.Key] != kvp.Value).ToArray();
//if (dqe.Length > 0)
//{
// if (Debugger.IsAttached)
// Debugger.Break();
// else
// throw new Exception();
//}
}
#endif
};
#if false
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public sealed partial class MarkingArrayTargetTfs : MarkingArrayTfs
{
public MarkingArrayTargetTfs(TypeMgr tm, int c_edge_hint)
: base(tm, c_edge_hint)
{
}
public Dictionary<Int64, Unification.UnifCoref> corefs = null;
/// Number of distinct coreferences
//public int c_corefs = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Prune a sub-graph, and then remove any unused coreferences (and unmark the edge coreference bit) which
/// have only a single use remaining.
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if false
public bool _prune_below(int i_feat, int m)
{
Edge e;
if (!TryGetEdge(i_feat, m, out e))
return false;
int c_reentrancies = 0;
Unification.UnifCoref uc = null;
if (e.FlagsId < 0)
{
/// find coreference for this edge
corefs.TryGetValue(((long)id << 32) | (uint)e.Mark, out uc);
while (uc.f_redirect)
uc = uc.next;
/// if we are pruning the opportunistic reentrancy hint, then clear it
if (uc.single_fm.i_feat == i_feat && uc.single_fm.m == m)
uc.single_fm = default(FeatMark);
c_reentrancies = --uc.c_fm;
e = uc.e_cur;
}
/// only remove *below* a coreferenced edge if it has no reentrancies remaining. This allows sub-graphs to
/// be pruned without disturbing the coreferenced portions that are still accessible from without.
if (c_reentrancies == 0 && (e.FlagsId & agree.Edge.Flag.EtmNonBareType) != 0)
foreach (int fix in tm.rgrgfix_by_type[(int)(e.FlagsId & Edge.Flag.MultiIdMask)])
_prune_below(fix, e.Mark);
/// remove the edge
if (!RemoveEdge(i_feat, m))
Debug.Assert(false);
/// all done if not coreferenced, or if additional reentrancies still point to this edge.
if (uc == null || c_reentrancies > 1)
return true;
/// 0 or 1 reentrancies remain. we will decrement the coreference count at the end of this function.
if (c_reentrancies == 1)
{
/// if there's were 2 reentrancies and now there's just 1 remaining, we're retaining *this* edge,
/// so clear its coreference bit, as stored by the *other* reentrancy, and discard the equivalence
/// class. We make these adjustments now, because that other edge might not be getting pruned,
/// so we might never encounter it. First, find out if the opportunistic hint is any good.
FeatMark fm = uc.single_fm;
if (fm.m == 0)
{
/// hint is no good; we must find the other reentrancy by exhaustive search
fm = this.FeatMarkEdges.First(fme =>
{
if (fme.e.FlagsId >= 0)
return false;
var ux = corefs[((long)id << 32) | (uint)fme.e.Mark];
while (ux.f_redirect)
ux = ux.next;
return ux == uc;
}).FeatMark;
}
Debug.Assert(ContainsFeatMark(fm.i_feat, fm.m));
uc.c_fm = 0;
#if DEBUG
uc.single_fm = default(FeatMark);
#endif
/// clear coreference bit (or remove) in the other reentrancy.
Edge.Flag nf = e.FlagsId & ~Edge.Flag.Coreference;
if (nf == 0)
RemoveEdge(fm.i_feat, fm.m);
else
SetEdge(fm.i_feat, fm.m, new Edge(nf, (nf & Edge.Flag.EtmNonBareType) == 0 ? 0 : e.Mark));
}
this.c_corefs--;
return true;
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public Tfs ToArrayTfs()
{
var matfs = new MarkingArrayTfs(this);
matfs.Name = this.Name;
return matfs;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public MotherDaughterTfs ToMotherDaughterTfs()
{
var tfs = new MotherDaughterTfs(this);
tfs.Name = this.Name;
return tfs;
}
};
#endif
}