#define EXHAUSTIVE_POOL_SEARCH using System; using System.Diagnostics; using System.Text; using System.IO; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; using glue.Extensions.Enumerable; using glue.Debugging; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// To abort processing at any point and send up a TFS for examination /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public class DebuggingTfsDisplayException : Exception { TfsEdge[] rgtfs; public DebuggingTfsDisplayException(TfsEdge tfs) : base(String.Format("Debugging exception for TFS {0}", tfs.ToString())) { this.rgtfs = new TfsEdge[] { tfs }; } public DebuggingTfsDisplayException(Tray tr, Edge e) : this(tr.CreateTfs(e)) { } public DebuggingTfsDisplayException(params TfsEdge[] rgtfs) { this.rgtfs = rgtfs; } public TfsEdge[] Tfs { get { return rgtfs; } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// To abort processing at any point and send up a TFS for examination /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public class DebuggingTfsDisplayExceptionWithHighlighting : DebuggingTfsDisplayException { TfsEdge tfsHighlight; public DebuggingTfsDisplayExceptionWithHighlighting(TfsEdge tfs, TfsEdge highlight) : base(tfs) { this.tfsHighlight = highlight; } public TfsEdge TfsHighlight { get { return tfsHighlight; } } } #if DEBUG /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: E D G E /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public partial struct Edge : IEquatable<Edge> { public override String ToString() { String s = FormatMark(this) + " " + _FlagsReport(FlagsId, false) + " "; if (Debugger.IsAttached || Nop.IsGuiApplication) return s; return s.Replace("⇌", "%").Replace("⊣", ".").Replace("☐", "_").Replace("☒", "X").Replace("⒮", "(s)"); } public Type _Type { get { return TrayMgr._most_recent_tray.tm.GetEdgeType(FlagsId); } } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] [DebuggerHidden] public ConstraintRef[] _FEATURES { get { return TrayMgr._most_recent_tray.AllConstraintRefs(this).ToArray(); } } static public String _FlagsReport(Flag f_in, bool f_coref) { Tray tr = TrayMgr._most_recent_tray; TypeMgr tm = tr.tm; String s = ""; if (f_coref && (f_in & Flag.Coreference) == Flag.Coreference) s += "⇌ "; if ((f_in & Flag.PrunedDuringParsing) == Flag.PrunedDuringParsing) s += "✗ "; Flag etm = f_in & Flag.EtmMask; if (etm == Flag.EtmString) { s += "⒮ "; String sv = tm.GetStringValue(f_in); if (sv != null) s += String.Format("\"{0}\" ", sv); } else { int id = (int)(f_in & tm.MultiIdMask); if (id == 0) s += "(*top*) "; else { //s += "id " + id.ToString() + " "; s += "(" + tm.type_arr[id].Name + ") "; } if (etm == Flag.EtmNonBareType) s += "… "; else if (etm == Flag.EtmConfigMapped) s += "✦ "; else s += "⊣ "; } return s; } public static String FormatMark(Edge e) { if (e.IsCoreferenced) return "⇌" + e.Mark.ToString(); if (e.Mark > Edge.MarkBare) return "@" + e.Mark.ToString(); if ((e.FlagsId & Edge.Flag.EtmNonBareType) != 0) return "☒"; return "☐"; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: T f s E d g e /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public partial struct TfsEdge : IEquatable<TfsEdge>, ParseChart.IMotherDaughter { public bool GetEdgeAtPath(FsPath p, out Edge e) { return TrayMgr.all_trays[ttid & 0x3F].GetEdgeAtPath(Edge, p, out e); } public Edge GetEdgeAtPath(String p) { Edge e; GetEdgeAtPath(new FsPath(p), out e); return e; } public Type GetTypeAtPath(String p) { Edge e = GetEdgeAtPath(p); return Tray.tm.GetEdgeType(e.FlagsId); } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] [DebuggerHidden] public ConstraintRef[] _BELOW { get { return Edge._FEATURES; } } #if false [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] [DebuggerHidden] public Tfs.CorefTarget[] CorefCounts { get { TfsEdge _this = this; // for lambda return GetCorefCounts().Select(ec => new Tfs.CorefTarget(_this, ec.edge, ec.count)).ToArray(); } } #endif //[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] //public IEnumerable<Tfs.CorefTarget> CorefCounts //{ // get // { // int _ttid = ttid; // for lambda // return GetCorefCounts().Select(ec => new Tfs.CorefTarget(_ttid, ec.edge, ec.count)); // } //} }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public partial struct EdgeCount { public override string ToString() { return String.Format("{0} count: {1}", edge, count); } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: T F S /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public partial class Tfs { public override string ToString() { return String.Format("{0}, {1} corefs", te, corefs.Length); } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] [DebuggerHidden] public CorefTarget[] _corefs { get { TfsEdge _this_te = this.te; return corefs.Select(c => new CorefTarget(_this_te, c.edge, c.count)).ToArray(); } } [DebuggerDisplay("{ToString(),nq}")] public struct CorefTarget { public CorefTarget(TfsEdge tfs, Edge e, int count) { this.te = tfs; this.count = count; this.paths = te.Tray.Roots .PathInfoStrings(e.Mark, true) .Select(tfsp => new FsPathInstance(tfs, tfsp.fsp)) .ToArray(); } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public FsPathInstance[] paths; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public TfsEdge te; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public int count; public override string ToString() { Edge e; paths[0].fsp.GetEdge(te, out e); return String.Format(" ↳ {0}: {1} in-edges, {2} paths", e, count, paths.Length); } }; [DebuggerDisplay("{ToString(),nq}")] public sealed class FsPathInstance { [DebuggerBrowsable(DebuggerBrowsableState.Never)] public readonly TfsEdge te_tfs; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public readonly TrayCompiledFsPath fsp; [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public PoolEdge[] _debug_display { get { return fsp .EnumeratePoolEdges(te_tfs.Edge.Mark) .ToArray(); } } public FsPathInstance(TfsEdge tfs, IEnumerable<String> rgs) { this.te_tfs = tfs; this.fsp = new TrayCompiledFsPath(tfs.Tray, rgs); } public override String ToString() { Edge e; fsp.GetEdge(te_tfs, out e); return " ↳ " + fsp.ToString().ToUpper() + ": " + e.ToString(); } }; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: P O O L M A R K /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public partial struct PoolMark : IEquatable<PoolMark>, IComparable<PoolMark> { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Warning: This is probably not what you want. We don't do an expensive and exhaustive search for the actual edge /// that led to this PoolMark (there are other debugging functions for that, see PathInfo()) so we use the pool/feature's /// maximal type to create the host. Also missing will be the coreference bit and I'm not sure what would happen with /// a string type. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public ConstraintRef _ConstraintRef { get { Edge.Flag f = (Edge.Flag)Pool.tm.GetMaximalTypeForFeature(Pool.i_feat).m_id; return new ConstraintRef(new Edge(f, in_mark), Pool); } } #if true || !EXHAUSTIVE_POOL_SEARCH public override String ToString() { if (Pool == null) return "default(PoolMark)"; return String.Format("({0}-{1})→{2}", Feature.ToUpper(), in_mark, Constraint); } #else public override String ToString() { if (Pool is UnknownPoolClass) return " (no feat.)"; String s = String.Empty; switch (GarbageType()) { case 0: s += "Ⓧ"; break; case 1: s += "ⓓ"; break; case 2: s += "ⓔ"; break; case 3: s += "ⓤ"; break; } s += String.Format("({0}-{1})→{2}", Feature.ToUpper(), in_mark, Constraint); if (ConstraintType.IsAtomic) s += "•"; return s; } PoolMark[] ReachableFrom { get { return _ReachableFrom().ToArray(); } } IEnumerable<PoolMark> _ReachableFrom() { foreach (ConstraintPool pool in this.Pool.tr.Pools) { foreach (var kvp_src_out in pool.PoolEdges) { if (kvp_src_out.Value.Mark == this.in_mark /*&& this.cp.AppropriateFor.Contains(kvp_src_out.Value.Type)*/) yield return new PoolMark(pool, kvp_src_out.Key); } } } int GarbageType() { if (_ReachableFrom().Any()) return 4; foreach (Type t in Pool.tm.feat_arr[Pool.FeatureIndex].AppropriateFor) { #if TOP_MARKS if (UnifyHelper.top_marks.Contains(this.in_mark)) return 3; #endif if (t.m_flags.HasFlag(Type.Flags.LoadedDefinition) && t.Definition.Mark == this.in_mark) return 1; if (t.m_flags.HasFlag(Type.Flags.Expanded) && t.Expanded.Mark == this.in_mark) return 2; } return 0; } #endif }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: C O N S T R A I N T R E F /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public partial struct ConstraintRef : IEquatable<ConstraintRef> { public override String ToString() { String s = Host.ToString(); if (Pool is UnknownPoolClass) s += " (no feat.)"; else { s += String.Format("{0} → {1}", Feature.ToUpper(), Constraint); if (ConstraintType.IsAtomic) s += "•"; } return s; } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public ConstraintRef[] _NextConstraint { get { return TrayMgr._most_recent_tray.AllConstraintRefs(this.Constraint).ToArray(); } } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: G L B D A G /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //[DebuggerDisplay("{m_level} {m_name,nq} {_OnesPositions(),nq}")] public abstract partial class GlbDag : Instance { /// Return a string that lists the integers corresponding to the 'set' bit positions in m_code String _OnesPositions() { int[] rg = m_code.OnesPositions().ToArray(); if (rg.Length == mgr.code_dict.Count) return "[all]"; return rg.StringJoin(" "); } Type GreatestLowerBound(Type other) { if (this.IsLeaf && other.IsLeaf) return null; HashSet<Type> cln = CommonLowerNodes(other); if (cln.Count == 0) return null; if (cln.Count == 1) return cln.First(); if (cln.Contains(this)) return this as Type; if (cln.Contains(other)) return other; throw new Exception(); } public HashSet<Type> CommonLowerNodes(Type other) { HashSet<Type> h = AllDescendantsInclusive; h.IntersectWith(other.AllDescendantsInclusive); return h; } /// only returns error cases public HashSet<Type> GlbCheck(Type other, Type root) { if (this as Type == other) return null; if (this.IsLeaf || other.IsLeaf) // one might be GLB, but there surely won't be a problem return null; if (this as Type == root || other == root) return null; HashSet<Type> cln = CommonLowerNodes(other); if (cln.Count <= 1 || cln.Contains(this as Type) || cln.Contains(other)) return null; // get rid of deeper extras HashSet<Type> h = new HashSet<Type>(); foreach (Type t in cln) h.UnionWith(t.AllDescendants); cln.RemoveWhere(e => h.Contains(e)); if (cln.Count == 0) throw new Exception(); // that might have done the trick if (cln.Count == 1) return null; return cln; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: T Y P E /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{Name,nq} {m_id} ({_feature_info(),nq})")] public partial class Type : GlbDag { public TypeMgr.FeatureInfo[] _dbg_features() { return fc.Select(i_feat => mgr.feat_arr[i_feat]).ToArray(); } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public ConstraintPool._DbgConstraintPool[] _FEATURES { get { if ((m_flags & Flags.LoadedNonLocalFeatures) == 0) return new ConstraintPool._DbgConstraintPool[0]; return _dbg_features().Select(fi => new ConstraintPool._DbgConstraintPool(fi, this)).ToArray(); } } String _feature_info() { int local = 0, total = 0; foreach (TypeMgr.FeatureInfo fi in _dbg_features()) { if (fi.maximal_type == this) local++; total++; } return String.Format("{0} features: {1} local, {2} inherited.", total, local, total - local); } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: T Y P E M A N A G E R /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial class TypeMgr { [DebuggerDisplay("#{i_feat} {feature.ToUpper()} ({maximal_type.Name})")] public partial struct FeatureInfo { }; public int GlbCount { get { return next_glb_num; } } public Instance FindExpanded(TfsEdge e) { return AllInstances.FirstOrDefault(_e => (_e.m_flags & Type.Flags.Expanded) > 0 && _e.Expanded.Equals(e)); } public Instance FindDefinition(TfsEdge e) { return AllInstances.FirstOrDefault(_e => _e.Definition.Equals(e)); } public String FindInfo(TfsEdge e) { foreach (Instance inst in AllInstances) { if (inst.Definition.Equals(e)) return "definition: " + inst.Name; if ((inst.m_flags & Type.Flags.Expanded) > 0 && inst.Expanded.Equals(e)) return "expanded: " + inst.Name; } return "unknown"; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: T R A Y /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// abstract public partial class Tray { #if EXHAUSTIVE_POOL_SEARCH public IEnumerable<PoolMark> TreeLeaves(IEnumerable<PoolMark> set) { return set.Where(pm => { Edge e = pm.Constraint; if (e.Mark == Edge.MarkBare) return true; if (e.IsCoreferenced && !_PoolMarksFromInMark(e.Mark).Any()) return true; return false; }); } #endif public IEnumerable<String> _ConstraintPaths(Edge e, String f) { bool f_any = false; foreach (var cp in ConstrainedPoolsOnly(e)) { foreach (var z in _ConstraintPaths(cp.GetEdge(e.Mark), (f != String.Empty ? f + "." : "") + cp.Feature.ToUpper())) { yield return z; f_any = true; } } if (!f_any) yield return f + " " + tm.GetEdgeType(e.FlagsId).Name; } /// used by TfsEdge debug code public bool GetEdgeAtPath(Edge e_start, FsPath p, out Edge e) { e = e_start; foreach (String f in p) { int i_feat = tm.GetFeatureIndex(f); if (i_feat == -1 || !Pools[i_feat].TryGetEdge(e.Mark, out e)) return false; } return true; } public void CheckOrphanedEdges(TextWriter tw, HashSet<PoolMark> reachable) { HashSet<PoolMark> pool_pms = new HashSet<PoolMark>(Pools.SelectMany(cp => cp.Marks.Select(m => new PoolMark(cp, m)))); //var y = pool_pms.OrderBy(x => x).ToArray(); //var z = reachable.OrderBy(x => x).ToArray(); #if BAREMARKS HashSet<PoolMark> bad_mark = new HashSet<PoolMark>(pool_pms.Where(pm => { Edge e = pm.Constraint; if (e.AnyConstraints || e.IsCoreferenced) return false; return e.Mark != 0; })); #endif HashSet<PoolMark> garbage = new HashSet<PoolMark>(pool_pms.Except(reachable)); HashSet<PoolMark> non_bare_garbage = new HashSet<PoolMark>(garbage.Where(pm => pm.Constraint.Mark != Edge.MarkBare)); HashSet<PoolMark> bare_garbage = new HashSet<PoolMark>(garbage.Where(pm => pm.Constraint.Mark == Edge.MarkBare)); //HashSet<PoolMark> garbage_trees = new HashSet<PoolMark>(garbage.Except(garbage.SelectMany(pm => pm.Constraint.ConstrainedPoolMarksOnly(this)))); HashSet<Edge> garbage_trees = TreeTops(garbage).ToHashSet(); //int garbage_parents = 0; // foreach (Edge ge in garbage) // { // if (ge.Any(ge_child => reachable.Contains(ge_child))) // garbage_parents++; // } tw.WriteLine("PoolMark Report:"); //tw.WriteLine(" in pools: {0,6}\n reachable: {1,6}\nmark should be 0: {2,6}\n garbage: {3,6}\n bare garbage: {4,6}\nnon-bare garbage: {5,6}", tw.WriteLine(" in pools: {0,7}\n reachable: {1,7}\n garbage: {2,7}\n bare garbage: {3,7}\nnon-bare garbage: {4,7}\n garbage trees: {5,7}", pool_pms.Count, reachable.Count, //bad_mark.Count, garbage.Count, bare_garbage.Count, non_bare_garbage.Count, garbage_trees.Count); int take_gt = int.MaxValue; if (garbage_trees.Count > 0) { tw.WriteLine(); tw.Write("Garbage Trees"); if (garbage_trees.Count > take_gt) tw.Write(" (first {0} of {1} shown)", take_gt, garbage_trees.Count); tw.WriteLine(); tw.WriteLine("==============================="); foreach (Edge gedge in garbage_trees.Take(take_gt)) { tw.WriteLine("\"{0}\"? @{1}", tm.GetEdgeType(gedge.FlagsId).Name, gedge.Mark); foreach (String pth in new PathLister(this, gedge, null, true, null))//reachable)) tw.WriteLine("\t{0}", pth); } tw.WriteLine("==============================="); } int take_g = 100; if (garbage.Count > 0) { tw.WriteLine(); tw.Write("Garbage PoolMarks:"); if (garbage.Count > take_g) tw.Write(" (first {0} of {1} shown)", take_g, garbage.Count); tw.WriteLine(); tw.WriteLine("==============================="); foreach (PoolMark gpm in garbage.Take(take_g)) tw.WriteLine(gpm.ToString()); tw.WriteLine("==============================="); } } #if EXHAUSTIVE_POOL_SEARCH public PoolMark[] PoolMarksFromOutMark(int m_out) { return _PoolMarksFromOutMark(m_out).ToArray(); } IEnumerable<PoolMark> _PoolMarksFromOutMark(int m_out) { foreach (ConstraintPool cp in Pools) foreach (var pe in cp.PoolEdges) if (pe.Value.Mark == m_out) yield return new PoolMark(cp, pe.Key); } IEnumerable<ConstraintPool> _PoolsFromOutMark(int m_out) { return Pools.Where(cp => cp.PoolEdges.Any(pe => pe.Value.Mark == m_out)); } #endif public PoolMark[] PoolMarksFromInMark(int m_in) { return _PoolMarksFromInMark(m_in).ToArray(); } IEnumerable<PoolMark> _PoolMarksFromInMark(int m_in) { return Pools.Where(p => p.ContainsInMark(m_in)).Select(cp => new PoolMark(cp, m_in)); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// debugging use only /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int FindTop(int mark) { int top_mark = mark; restart: foreach (var pe in Pools.SelectMany(cp => cp.PoolEdges)) { if (pe.Value.Mark == top_mark) { top_mark = pe.Key; goto restart; } } return top_mark; } public Edge SynthesizeTopEdge(int mark) { var rgcp = _PoolsFromOutMark(mark).ToArray(); if (rgcp.Length == 0) return default(Edge); Type t = rgcp.Select(cp => cp.IntroducedBy).ArgMax(tt => tt.m_level); return CreateRecycledEdge(t, mark, false); } public Edge SynthesizeTopEdge(Edge edge) { return SynthesizeTopEdge(FindTop(edge.Mark)); } [DebuggerBrowsable(DebuggerBrowsableState.Never)] RootAnalysis ra = null; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public RootAnalysis Roots { get { return ra = ra ?? new RootAnalysis(this); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public class RootAnalysis { Tray tr; Dictionary<int, RootEdgeData> roots = new Dictionary<int, RootEdgeData>(); public RootAnalysis(Tray tr) { this.tr = tr; foreach (Instance t in tr.tm.AllInstances) { int mx_d; mx_d = t.Definition.Edge.Mark; if (mx_d != 0) { int mx_e = 0; if ((t.m_flags & Type.Flags.Expanded) > 0) { if ((mx_e = t.Expanded.Edge.Mark) != 0 && mx_e != mx_d) roots.Add(mx_e, new RootEdgeData(t, RootEdgeType.Expanded, mx_e)); } if (mx_d == mx_e) roots.Add(mx_d, new RootEdgeData(t, RootEdgeType.ExpandedDefinition, mx_d)); else roots.Add(mx_d, new RootEdgeData(t, RootEdgeType.Definition, mx_d)); } } } [Flags] public enum RootEdgeType { Unknown = 0, Definition = 1, Expanded = 2, ExpandedDefinition = 3, CycleDetected = 4, }; [DebuggerDisplay("{ToString(),nq}")] public struct RootEdgeData { public RootEdgeData(Instance t, RootEdgeType ret, int mark) { this.t = t; this.ret = ret; this.mark = mark; } public Instance t; public RootEdgeType ret; public int mark; public override String ToString() { if (ret == RootEdgeType.Unknown || ret == RootEdgeType.CycleDetected) return ret.ToString(); return String.Format("{0} {1} {2}", t.Name, ret, Edge.FormatMark(new Edge(0, mark))); } }; public Instance FindRoot(int m) { RootEdgeData red; return roots.TryGetValue(tr.FindTop(m), out red) ? red.t : null; } public RootEdgeData FindRootData(int m) { RootEdgeData red; return roots.TryGetValue(tr.FindTop(m), out red) ? red : default(RootEdgeData); } [DebuggerDisplay("{ToString(),nq}")] public struct TaggedFsPath { public RootEdgeData red; public FsPath fsp; public override string ToString() { return String.Format("{0} {1}", red.ret == RootEdgeType.Unknown ? "???" : red.ToString(), fsp.ToString()); } }; #if EXHAUSTIVE_POOL_SEARCH class PathInfoFinder { RootAnalysis ra; int m_in; bool f_short; List<TaggedFsPath> paths = new List<TaggedFsPath>(); public PathInfoFinder(RootAnalysis ra, int m_in, bool f_short) { this.ra = ra; this.m_in = m_in; this.f_short = f_short; _find(m_in, new List<KeyValuePair<int, String>>()); } void _find(int m, List<KeyValuePair<int, String>> path) { Debug.Assert(m != 0); RootEdgeData red; if (path.Any(kvp => kvp.Key == m)) { paths.Add(new TaggedFsPath { fsp = new FsPath(path.Select(kvp => kvp.Value).Reverse()), red = new RootEdgeData(null, RootEdgeType.CycleDetected, 0) }); throw new Exception("cyclical path"); //return; } //if (ra.roots.TryGetValue(m, out red)) //{ // paths.Add(new TaggedFsPath { fsp = new FsPath(path.Select(kvp => kvp.Value).Reverse()), red = red }); // return; //} bool f_any = false; path.Add(default(KeyValuePair<int, string>)); foreach (var cp in ra.tr.Pools) { foreach (var pe in cp.PoolEdges) { Edge e = pe.Value; if (e.Mark == m) { String sx; if (f_short) sx = cp.Feature; else sx = String.Format("[{0} {1} {2}]", cp.Feature.ToUpper(), ra.tr.tm.GetEdgeType(e.FlagsId).Name, Edge.FormatMark(e)); path[path.Count - 1] = new KeyValuePair<int, String>(m, sx); if (ra.roots.TryGetValue(m, out red)) paths.Add(new TaggedFsPath { fsp = new FsPath(path.Select(kvp => kvp.Value).Reverse()), red = red }); f_any = true; _find(pe.Key, new List<KeyValuePair<int, String>>(path)); } } } if (!f_any) { path.RemoveAt(path.Count - 1); paths.Add(new TaggedFsPath { fsp = new FsPath(path.Select(kvp => kvp.Value).Reverse()), red = new RootEdgeData(null, RootEdgeType.Unknown, 0) }); } } public List<TaggedFsPath> Result { get { return paths; } } }; public List<TaggedFsPath> PathInfoStrings(int m_in, bool f_short = false) { if (m_in == 0) return new List<TaggedFsPath>(); var r = new PathInfoFinder(this, m_in, f_short).Result; return r; } public String PathInfo(int m_in) { return PathInfoStrings(m_in).StringJoin(Environment.NewLine); } #endif }; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: U N I F I C A T I O N /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public abstract partial class Unification { static int next_id = 0; public readonly int id; [DebuggerDisplay("{ToString(),nq}")] sealed partial class UnifCoref : List<TfsEdge> { static int next_id = 0xCF00; readonly public int id; public Unification uh; public UnifCoref(Unification uh) { this.uh = uh; this.id = Interlocked.Increment(ref next_id); } TfsEdge[] DictionaryKeys() { return uh.corefs.Where(kvp => kvp.Value == this).Select(kvp => kvp.Key).ToArray(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// dst_map includes only PoolMarks which refer to the target TFS instance, that is, the one that is currently /// currently being constructed by unification. /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IEnumerable<PoolMark> PoolMarks() { return pmx; } public override string ToString() { #if true return String.Format("{0} — {1} {2} PMs █ {3} █ {4}", this.id.ToString("X4"), Master.ToString(), pmx.Count, PoolMarks().Select(z => z.ToString()).StringJoin(" ▎"), this.StringJoin(" ")); #else var te_keys = uh.corefs.Where(kvp => kvp.Value == this).Select(kvp => kvp.Key).ToArray(); HashSet<TfsEdge> c = new HashSet<TfsEdge>(this); c.IntersectWith(te_keys); String a = te_keys.Except(c).Select(te => "[" + te + "]").StringJoin(" "); String b = this.Except(c).Select(te => "{" + te + "}").StringJoin(" "); return String.Format("{0} — {1} {2} PMs █ {3} █ {4} {5} {6}", this.id.ToString("X4"), Master.ToString(), pmx.Count, PoolMarks().Select(z => z.ToString()).StringJoin(" ▎"), a, c.StringJoin(" "), b); #endif } }; public partial class Expander : Unification { Type _t_exp; } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// /// debug: G R A M M A R /// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial class Grammar : IGrammar { public String GarbageReport(HashSet<PoolMark> hspm = null) { hspm = hspm ?? Reachable(); using (StringWriter sw = new StringWriter()) { loadtray.CheckOrphanedEdges(sw, hspm); return sw.ToString(); } } }; #else //DEBUG public partial class Grammar { public String GarbageReport(HashSet<PoolMark> hspm = null) { return "release build - no garbage report"; } }; #endif // DEBUG }