#if DEBUG
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Collections;
using System.Runtime.InteropServices;
using miew.Debugging;
using miew.Enumerable;
using miew.ReadOnly;
namespace agree
{
[DebuggerDisplay("{ToString(),nq}")]
public unsafe partial class UnificationQd
{
[DebuggerDisplay("{ToString(),nq}")]
public struct TfsixMark : IEquatable<TfsixMark>
{
public TfsixMark(short tfsix, int mark)
{
this.tfsix = tfsix;
this.mark = mark;
}
public TfsixMark(TfsixEdge te)
{
this.tfsix = te.tfsix;
this.mark = te.e.Mark;
}
public int mark;
public short tfsix;
public bool Equals(TfsixMark other)
{
return this.mark == other.mark && this.tfsix == other.tfsix;
}
public override string ToString()
{
return String.Format("tfsix: {0} mark: {1}", tfsix, mark);
}
};
public static System.IO.TextWriter dtw;
static UnificationQd _singleton;
public Scratch* _ps0, _ps1;
public Stack<int> stk;
public string CurrentPath { get { return stk == null ? "" : stk.Reverse().Select(fix => tm.feat_arr[fix].feature).StringJoin("."); } }
[DebuggerStepThrough]
void _check_args(Edge.Flag f, Scratch* ps0, Scratch* ps1)
{
Debug.Assert(ps0->tfsix > 0 && ps1->tfsix > 0);
Debug.Assert(ps0->m_src != 0 && ps1->m_src != 0);
Debug.Assert(ps0->m_src != ps1->m_src || ps0->tfsix != ps1->tfsix);
Debug.Assert(*rgpfix[(int)(f & Edge.Flag.MultiIdMask)] > 0);
//if (Debugger.IsAttached)
//{
// _ps0 = bases[tfsix0] + (m0 < 0 ? m0 : m0 == TopmostMark ? 0 : GetMix(tfsix0, m0));
// _ps1 = bases[tfsix1] + (m1 < 0 ? m1 : m1 == TopmostMark ? 0 : GetMix(tfsix1, m1));
// Debug.Assert(_ps0 != _ps1);
//}
if (stk != null)
stk.Push(0);
}
[DebuggerHidden]
void _change_stack_top(ushort i_feat)
{
if (stk != null)
{
stk.Pop(); stk.Push(i_feat);
}
}
[DebuggerHidden]
void _debug_nps(Scratch* ps0, Scratch* ps1, Scratch* nps0, Scratch* nps1)
{
if (dtw != null)
{
sbyte suppress = 0;
if (ps0->c_visits != 0)
suppress++;
if (ps1->c_visits != 0)
suppress++;
if (nps0 == null && nps1 == null)
{ }
else if (nps0 == null)
dtw.WriteLine("D {0} {1} {2,-75} {3,-3} {4,2} {5,2} -> {6,2} {7,2} {8,-38} {9}", " ", nps1->tfsix, CurrentPath.ToUpper(), suppress == 0 ? "" : "s" + suppress.ToString(), ps0->c_visits, ps1->c_visits, " ", nps1->c_visits, "null", ShortInfo2a(nps1));
else if (nps1 == null)
dtw.WriteLine("D {0} {1} {2,-75} {3,-3} {4,2} {5,2} -> {6,2} {7,2} {8,-38} {9}", nps0->tfsix, " ", CurrentPath.ToUpper(), suppress == 0 ? "" : "s" + suppress.ToString(), ps0->c_visits, ps1->c_visits, nps0->c_visits, " ", ShortInfo2a(nps0), "null");
else
dtw.WriteLine("D {0} {1} {2,-75} {3,-3} {4,2} {5,2} -> {6,2} {7,2} {8,-38} {9}", nps0->tfsix, nps1->tfsix, CurrentPath.ToUpper(), suppress == 0 ? "" : "s" + suppress.ToString(), ps0->c_visits, ps1->c_visits, nps0->c_visits, nps1->c_visits, ShortInfo2a(nps0), ShortInfo2a(nps1));
}
}
[DebuggerHidden]
void _debug_nps_single(Scratch* ps, Scratch* nps)
{
if (dtw != null)
{
dtw.WriteLine("U {0} {1,-75} {2,-3} {3,2} -> {4,2} {5}",
nps->tfsix,
CurrentPath.ToUpper(),
ps->c_visits != 0 ? "s1" : "",
ps->c_visits,
nps->c_visits,
ShortInfo2a(nps));
}
}
void _check_counts(arr_tfs_entry[] entries, Scratch* ps_m)
{
//var chkarr = entries
// .GroupBy(ate => ate.e_Mark)
// .Select(g => new { e = g.First().e, mark = g.Key, count = g.Count(), fmx = g.Select(xg => xg.fm).ToArray() })
// .Where(g => g.count > 1)
// .OrderBy(g => g.mark)
// .ToArray();
chkarr = entries
.Take(i_ate)
.GroupBy(ate => ate.e_Mark)
.ToDictionary(g => g.Key, g => g.Count());
chktfs = entries
.Take(i_ate)
.GroupBy(ate => ate.mark)
.ToDictionary(g => g.Key, g => g.ToDictionary(xx => xx.i_feat, xx => xx.e));
_check_counts(TopmostMark, ps_m);
//Debug.Print("ent: {0,3} c_edges: {1,3} c_tot: {2,3} c_totns: {3,3} ps->d->c_visits {4} ps_x->forward {5}",
// entries.Length, c_edges, c_tot, c_totns, ps_d->c_visits, ps_x->forward);
if (c_edges != entries.Length)
{
Console.Out.WriteColorSync("$red [{0} {1} {2}] ", c_edges, entries.Length, ctrl.ts_input.Source.Text);
}
else
{
//Console.Write(".");
}
}
Scratch* true_bases(int tfsix)
{
if (tfsix > c_participants + 1)
throw new Exception();
if (tfsix == c_participants + 1)
return next_base;
return bases[tfsix] + participants[tfsix].next_coref_mark + 1;
}
Dictionary<int, int> chkarr;
Dictionary<int, Dictionary<int, Edge>> chktfs;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void _check_counts(int m_reference, Scratch* ps)
{
Dictionary<int, Edge> d;
chktfs.TryGetValue(m_reference, out d);
ArrayTfs tfs = participants[ps->tfsix];
ushort* pfix = rgpfix[(int)(ps->f & Edge.Flag.MultiIdMask)], pfix_end = *pfix++ + pfix;
do
{
if (stk != null) stk.Push(*pfix);
{
Scratch* nps = _fallback_fetch(tfs, ps, *pfix);
if (nps == null || nps->tfsix == 0)
goto _continue;
Edge ne1;
if (!d.TryGetValue(*pfix, out ne1))
{
Debug.Assert(nps->m_copy == 0, "Count failed", "#2, Input: {0}", ctrl.ts_input.Source.Text);
Debug.Assert(nps->f == 0, "Count failed", "#3, Input: {0}", ctrl.ts_input.Source.Text);
//Debug.Assert(nps->c_visits <= 1);
}
else
{
Debug.Assert(ne1.Mark == nps->m_copy, "Count failed", "#4, Input: {0}", ctrl.ts_input.Source.Text);
Debug.Assert(ne1.FlagsId == nps->f, "Count failed", "#5, Input: {0}", ctrl.ts_input.Source.Text);
int expected = nps->c_visits > 1 ? chkarr[ne1.Mark] : 1;
Debug.Assert(expected == nps->c_visits, "Count failed", "#6, Input: {0}", ctrl.ts_input.Source.Text);
if ((nps->f & Edge.Flag.EtmNonBareType) != 0)
_check_counts(ne1.Mark, nps);
}
}
_continue: ;
if (stk != null) stk.Pop();
}
while (++pfix < pfix_end);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Scratch* _get_address(byte tfsix, int mix, int nm)
{
Debug.Assert(tfsix != 0);
return bases[tfsix] + (nm < 0 ? nm : mix);
}
public Edge GetArgArrayTfsEdge(Scratch* ps)
{
Debug.Assert(c_participants > 0 && ps >= true_bases(1));
int tfsix = GetTfsix(ps);
Tfs tfs = participants[tfsix];
int mix = (int)(ps - bases[tfsix]);
if (mix > 0)
{
if (tfs is ArrayTfs)
return ((ArrayTfs)tfs).entries[mix - 1].e;
else
return default(Edge);
}
else if (mix == 0)
{
Debug.Assert(tfs.Edge.Mark == TopmostMark);
return tfs.Edge;
}
return tfs.GetCorefEdge(mix);
}
FeatMark GetFm(Scratch* ps)
{
int tfsix = GetTfsix(ps);
return GetFmFromMix(tfsix, (int)(ps - bases[tfsix]));
}
FeatMark GetFmFromMix(int tfsix, int mix)
{
if (mix <= 0)
return default(FeatMark);
return participants[tfsix].entries[mix - 1].fm;
}
//int GetMix(int tfsix, int m)
//{
// Debug.Assert(m != 0);
// if (m <= 0)
// return m;
// ArrayTfs tfs = participants[tfsix];
// FeatMark fm = tfs.GetHostFeatMark(m);
// Debug.Assert(fm.m != 0);
// m = fm.m;
// return tfs.GetEdgeIndex(fm.i_feat, ref m);
//}
int GetTfsix(Scratch* ps)
{
//Debug.Assert(c_participants > 0 && ps >= true_bases[1]);
if (IsInitialized(ps))
return ps->tfsix;
int tfsix = 1;
while (ps >= true_bases(tfsix + 1))
tfsix++;
return tfsix;
}
public static bool IsInitialized(Scratch* ps) { return ps->tfsix != 0; }
public static bool IsMaster(Scratch* ps) { return IsInitialized(ps) && ps->forward >= 0; }
public bool AreJoined(Scratch* ps0, Scratch* ps1)
{
_dereference(ref ps0);
_dereference(ref ps1);
return ps0 == ps1;
}
public IList<ScratchDebug> _forwarders(Scratch* ps_seek)
{
if (!IsInitialized(ps_seek))
return new ScratchDebug[0];
_dereference(ref ps_seek);
List<ScratchDebug> lsd = new List<ScratchDebug>();
Scratch* ps = ps_base + 1;
Scratch* ps_end = ps_base + c_slot_alloc;
while (ps < ps_end)
{
if (ps->forward < 0)
{
Scratch* _tmp = ps;
do
_tmp = ps_base - _tmp->forward;
while (_tmp->forward < 0);
if (_tmp == ps_seek)
lsd.Add(new ScratchDebug(this, ps));
}
ps++;
}
return lsd;
}
public override string ToString()
{
String s = String.Format("c_tfs: {0} c_edges {1} ", c_participants, 0);//c_edges);
s += "\"" + CurrentPath + "\"";
if (_ps0 != null && _ps1 != null)
{
s += String.Format(" {0} ⊓ {1}",
"{" + ShortInfo2(_ps0) + "}",
"{" + ShortInfo2(_ps1) + "}");
}
return s;
}
[DebuggerDisplay("{ToString(),nq}")]
public struct ParticipantInfo
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
UnificationQd u;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
byte tfsix;
public ParticipantInfo(UnificationQd u, byte tfsix)
{
this.u = u;
this.tfsix = tfsix;
}
//[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public ArrayTfs ArrayTfs { get { return u.participants[tfsix] as ArrayTfs; } }
public ScratchDebug[] _scr_debug
{
get
{
int c = _slot_count(u.participants[tfsix], null);
ScratchDebug[] rgsd = new ScratchDebug[c];
for (int i = 0; i < c; i++)
rgsd[i] = new ScratchDebug(u, tfsix, i);
return rgsd;
}
}
public ScratchDebug[] _scr_debug_in_use
{
get
{
List<ScratchDebug> lsd = new List<ScratchDebug>();
int c = _slot_count(u.participants[tfsix], null);
Scratch* ps = u.true_bases(tfsix);
for (int i = 0; i < c; i++, ps++)
if (IsInitialized(ps))
lsd.Add(new ScratchDebug(u, tfsix, i));
return lsd.ToArray();
}
}
public ScratchDebug[] _scr_forwarded
{
get
{
List<ScratchDebug> lsd = new List<ScratchDebug>();
int c = _slot_count(u.participants[tfsix], null);
Scratch* ps = u.true_bases(tfsix);
for (int i = 0; i < c; i++, ps++)
if (ps->forward < 0)
lsd.Add(new ScratchDebug(u, tfsix, i));
return lsd.ToArray();
}
}
public override string ToString()
{
Tfs tfs = u.participants[tfsix];
int offs, c = _slot_count(tfs, &offs);
String rs = String.Format("[{0}...{1}...{2}]",
(int)(u.true_bases(tfsix) - u.ps_base),
(int)(u.bases[tfsix] - u.ps_base),
(int)((u.true_bases(tfsix + 1) - 1) - u.ps_base));
String s = String.Format("{0,17} tfsix: {1} [{2} {3}/{4}] ({5}) {6}",
rs,
tfsix,
-offs,
tfs.next_mark - 1,
tfs.ScratchAlloc,
c,
tfs);
return s;
}
}
[DebuggerDisplay("{ToString(),nq}")]
public partial struct Scratch
{
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public ScratchDebug _src_debug
{
get { return new ScratchDebug(_singleton, _this); }
}
public override string ToString()
{
return new ScratchDebug(_singleton, _this).ToString();
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// tfsix : index of the TFS in participants[...]
/// rix : raw, mixed index within a single TFS
/// mix : mixed index adjusted to be referenced off bases[tfsix]
/// 'mark' if less than zero. it is always valid to reference bases[tfsix]+mix with it
/// gix : global index of any Scratch field, based only on ps_base
/// global slot 0 is reserved for indicating 'no forwarding'
/// ps : pointer to scratch structures
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
[DebuggerDisplay("{ToString(),nq}")]
public struct ScratchDebug
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
UnificationQd u;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
int tfsix;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
int rix;
[DebuggerHidden]
public ScratchDebug(UnificationQd u, int tfsix, int rix)
{
this.u = u;
this.tfsix = tfsix;
this.rix = rix;
}
[DebuggerHidden]
public ScratchDebug(UnificationQd u, int tfsix, Scratch* ps)
: this(u, ps == null ? 0 : tfsix, ps == null ? -1 : (int)(ps - u.true_bases(tfsix)))
{
}
[DebuggerHidden]
public ScratchDebug(UnificationQd u, Scratch* ps)
: this(u, u.GetTfsix(ps), ps)
{
}
//[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public TfsEdge _dbg_node
{
get
{
if (tfsix == 0 || rix == -1)
return default(TfsEdge);
Scratch* ps = u.true_bases(tfsix) + rix;
if (!IsInitialized(ps))
return default(TfsEdge);
return u.participants[tfsix].GetSectionTfsEdge(u.GetArgArrayTfsEdge(ps));
}
}
public ScratchDebug[] _references
{
get
{
if (tfsix == 0 || rix == -1)
return null;
var rg = u._forwarders(u.true_bases(tfsix) + rix);
return rg as ScratchDebug[] ?? rg.ToArray();
}
}
public ScratchDebug _fwd_target
{
get
{
if (tfsix == 0 || rix == -1)
return this;
Scratch* ps_fwd = u.true_bases(tfsix) + rix;
if (!IsInitialized(ps_fwd))
return this;
u._dereference(ref ps_fwd);
return new ScratchDebug(u, ps_fwd);
}
}
public override string ToString()
{
Scratch* ps_this = u.true_bases(tfsix) + rix;
//if (!IsInitialized(ps_this))
// return "(?)";
String s = String.Format("{0} ", u.ShortInfo1(ps_this));
int om = 0;
String s1;
int mix = (int)(ps_this - u.bases[tfsix]);
if (mix < 0)
s1 = String.Format("m {0,3}", mix);
else if (mix == 0)
s1 = "TOPMST";
else
{
ArrayTfs tfs = u.participants[tfsix];
s1 = "[" + (mix - 1) + "] ";
arr_tfs_entry ate = tfs.entries[mix - 1];
if (ate.mark != 0)
{
s1 += ate.mark + "/" + u.tm.feat_arr[ate.i_feat].feature.ToUpper();
om = ate.e_Mark;
}
}
s += String.Format("{0,-20} ", s1);
if (ps_this->tfsix == 0)
{
if (om < 0)
s += " " + om;
}
else
{
if (ps_this->forward >= 0)
{
s += String.Format("{0,26} ", Edge._FlagsReport(ps_this->f, false));
//if (ps_this->forward != FirstVisit && ps_this->forward != Terminator)
// s += "Error c_ref != 0, forwarded. ";
s += String.Format("visit: {0} ", ps_this->c_visits);
//if ((ps_this->c_ref > 1) != (ps_this->c_visits > 1))
// s += "≠ ";
if (ps_this->forward != 0)
s += String.Format("(fwd: {0}) ", ps_this->forward);
}
else
{
if (ps_this->m_src != 0)
s += String.Format("m{0} ", ps_this->m_src).PadLeft(27);
else
s += "☐ ".PadLeft(27);
//if (ps_this->c_ref != 0)
// s += String.Format("ERROR c_ref=={0}. ", ps_this->c_ref);
//if (ps_this->c_ref == 0)
{
Scratch* ps_fwd = ps_this;
u._dereference(ref ps_fwd);
s += "fwd: {" + u.ShortInfo2(ps_fwd) + "} ";
}
}
}
return s;
}
};
public String ShortInfo0(Scratch* ps)
{
int tfsix = GetTfsix(ps);
return String.Format("{0}@{1}", tfsix, GetFm(ps));
}
public String ShortInfo0a(Scratch* ps)
{
int tfsix = GetTfsix(ps);
int mix = (int)(ps - bases[tfsix]);
String s = String.Format("{0}@{1}", tfsix, (int)(ps - true_bases(tfsix)));
if (mix < 0)
s += String.Format("({0})", mix.ToString());
else if (mix > 0)
s += String.Format("({0})", GetFmFromMix(tfsix, mix).ToString());
return s;
}
public String ShortInfo1(Scratch* ps)
{
int tfsix = GetTfsix(ps);
return String.Format("{0,3}:{1}@{2,-3}", (int)(ps - ps_base), tfsix, (int)(ps - true_bases(tfsix)));
}
public String ShortInfo2(Scratch* ps)
{
String s = ShortInfo0a(ps);
if (IsInitialized(ps))
{
if (IsMaster(ps))
{
s += " " + Edge._FlagsReport(ps->f, false);
s += ", visit: " + ps->c_visits;
}
else
s += "m" + ps->m_src;
}
return s;
}
public String ShortInfo2a(Scratch* ps)
{
String s = ShortInfo0a(ps);
if (IsInitialized(ps))
{
if (IsMaster(ps))
{
s += " " + Edge._FlagsReport(ps->f, false);
if (ps->m_copy != 0)
s += " -> " + ps->m_copy.ToString();
}
else if (ps->m_src != 0)
s += " m" + ps->m_src;
}
return s;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public ParticipantInfo[] _dbg_participants
{
get
{
return Enumerable.Range(1, c_participants).Select(i => new ParticipantInfo(this, (byte)i)).ToArray();
}
}
};
}
#endif