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(); }
};
}