#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