using System; using System.Diagnostics; using System.IO; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Collections.Concurrent; using System.Runtime.Serialization; using miew.String; using miew.String.Builder; using miew.Debugging; using miew.Enumerable; namespace agree { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public struct PathEdge { public PathEdge(IEnumerable<int> fix_path, Edge e) { this.path = fix_path as int[] ?? fix_path.ToArray(); this.e = e; } public int[] path; public Edge e; #if DEBUG public override string ToString() { return String.Format("{0} {1}", path.Select(fix => Grammar._singleton.tm.feat_arr[fix].feature.ToUpper()).StringJoin("."), e); } #endif }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public struct FsPathPair { public FsPathPair(FsPath path1, FsPath path2) { this.path1 = path1; this.path2 = path2; } public FsPathPair(String s1, String s2) { this.path1 = new FsPath(s1); this.path2 = new FsPath(s2); } public FsPath path1; public FsPath path2; }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public sealed class FsPath : IList<String>, IEquatable<FsPath> { static public readonly FsPath Empty = new FsPath(new String[0]); static readonly Char[] dot_space = { '.', ' ' }; static readonly Char[] outer_trim = { '\"', '\'', '(', ')', '[', ']' }; readonly String[] arr; readonly int hc; public FsPath(IEnumerable<String> rgs) { /// interning strings here in order to guarantee the sufficiency of explicit reference /// equality in the Equals() override this.arr = rgs.Select(s => String.Intern(s.ToLower().Trim())).Where(s => !String.IsNullOrEmpty(s)).ToArray(); hc = arr.Length; for (int i = 0; i < arr.Length; i++) hc = hc ^ (i + arr[i].GetHashCode()); } public FsPath(String s) : this(s.Trim(outer_trim).Split(dot_space, StringSplitOptions.RemoveEmptyEntries)) { } public String this[int index] { get { return arr[index]; } set { throw new InvalidOperationException(); } } public int IndexOf(String item) { return Array.IndexOf<String>(arr, item); } public bool Contains(String item) { return Array.IndexOf<String>(arr, item) != -1; } public void CopyTo(String[] array, int arrayIndex) { Array.Copy(arr, array, arr.Length); } public int Count { get { return arr.Length; } } public bool IsReadOnly { get { return true; } } public IEnumerator<String> GetEnumerator() { return arr.AsEnumerable<String>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return arr.GetEnumerator(); } public void Insert(int index, string item) { throw new InvalidOperationException(); } public void RemoveAt(int index) { throw new InvalidOperationException(); } public void Add(String item) { throw new InvalidOperationException(); } public void Clear() { throw new InvalidOperationException(); } public bool Remove(String item) { throw new InvalidOperationException(); } public bool StartsWith(FsPath b) { if (Object.Equals(this, b)) return true; int n = b.arr.Length; if (arr.Length < n) return false; for (int i = 0; i < n; i++) if (!Object.Equals(arr[i], b.arr[i])) return false; return true; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// 'Object' overrides (and related) /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool Equals(FsPath other) { if (other == null || hc != other.hc) return false; for (int i = 0; i < arr.Length; i++) if (!Object.Equals(arr[i], other.arr[i])) return false; return true; } public override bool Equals(Object obj) { FsPath o = obj as FsPath; return o != null && hc == o.hc && this.Equals(o); } public override int GetHashCode() { return hc; } public override String ToString() { return arr.StringJoin(".").ToUpper(); } }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DebuggerDisplay("{ToString(),nq}")] public class TypeMgrCompiledFsPath : IEquatable<TypeMgrCompiledFsPath>, IEnumerable<int> { readonly protected int[] rg_fix; readonly int hc; readonly protected TypeMgr tm; public TypeMgrCompiledFsPath(TypeMgr tm, IEnumerable<int> rgfix) { this.tm = tm; this.rg_fix = rgfix.ToArray(); hc = rg_fix.Length; for (int i = 0; i < rg_fix.Length; i++) { int fix = rg_fix[i]; Debug.Assert(fix.GetHashCode() == fix); if (fix == -1) { Array.Resize(ref rg_fix, i); break; } hc = hc ^ (i + fix); } } public TypeMgrCompiledFsPath(TypeMgr tm, IEnumerable<String> ies) : this(tm, ies.Select(s => { FeatureInfo fi; return tm.feat_map.TryGetValue(s, out fi) ? fi.i_feat : -1; })) { } public TypeMgrCompiledFsPath(TypeMgr tm, FsPath fsp) : this(tm, (IEnumerable<String>)fsp) { } public TypeMgr TypeMgr { get { return tm; } } public bool GetEdge(Tfs tfs, out Edge e) { e = tfs.Edge; foreach (int i in rg_fix) { if (e.Mark == 0 || !tfs.TryGetEdge(i, e.Mark, out e)) return false; } return true; } public int GetMark(Tfs tfs) { Edge e = tfs.Edge; foreach (int i in rg_fix) { if (e.Mark == 0 || !tfs.TryGetEdge(i, e.Mark, out e)) throw new Exception(); } return e.Mark; } public IEnumerable<PathEdge> GetListPathEdges(Tfs tfs) { Edge e = tfs.Edge; foreach (int i in rg_fix) { if (e.Mark == 0 || !tfs.TryGetEdge(i, e.Mark, out e)) yield break; } /// e.Type must unify down to tt_list_parent, but we don't need to check this separately because the ListHead pool /// is only appropriate for types that are lists, so the Mark won't be found if e.Type is not a list. Edge lh_edge; List<int> fix_path = new List<int>(rg_fix.Length + 4); fix_path.AddRange(rg_fix); while (tfs.TryGetEdge(tm.f_ix_list_head, e.Mark, out lh_edge)) { fix_path.Add(tm.f_ix_list_head); yield return new PathEdge(fix_path, lh_edge); fix_path[fix_path.Count - 1] = tm.f_ix_list_tail; if (!tfs.TryGetEdge(tm.f_ix_list_tail, e.Mark, out e) || e.Mark == 0) yield break; } } public IEnumerable<ConstraintRef> WalkPath(Tfs tfs) { Edge e = tfs.Edge; foreach (int i in rg_fix) { yield return new ConstraintRef(tfs, e, i); if (e.Mark == 0 || !tfs.TryGetEdge(i, e.Mark, out e)) throw new Exception(); } } public Type GetType(Tfs tfs) { Edge e = tfs.Edge; foreach (int i in rg_fix) if (e.Mark == 0 || !tfs.TryGetEdge(i, e.Mark, out e)) return null; return tm.GetEdgeType(e.FlagsId); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// 'Object' overrides /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public bool Equals(TypeMgrCompiledFsPath other) { if (other == null || hc != other.hc) return false; for (int i = 0; i < rg_fix.Length; i++) if (rg_fix[i] != other.rg_fix[i]) return false; return true; } public override bool Equals(object obj) { throw new NotImplementedException("Please use strongly-typed override."); } public override int GetHashCode() { return hc; } public override String ToString() { return rg_fix.Select(i => tm.feat_arr[i].feature).StringJoin("."); } public IEnumerator<int> GetEnumerator() { return rg_fix.AsEnumerable<int>().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }; }