using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Linq;
using miew.Tokenization;
using miew.Debugging;
namespace agree
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// base class for (also nested) Derived and Completed passive chart edges. This associaties a TFS with the parsing
/// activities coordinated by a ParseControl instance
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public abstract partial class PassiveEdge : ArrayTfs, IParseObj
{
public PassiveEdge(ParseControl ctrl, Span sp, Entry license, Tfs tfs)
: base(tfs)
{
this.ctrl = ctrl;
this.span = sp;
this.license = license;
}
public ParseControl ctrl;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// ITokenSpan, ICharacterSpan
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Span span;
public Span TokenSpan { get { return span; } }
public Span CharacterSpan { get { throw new NotImplementedException(); } }
public String Text { get { return ctrl.ts_input.Source.MinimalSpanText(span); } }
public bool IsEntireSpan { get { return TokenSpan.Equals(ctrl.chart.EntireSpan); } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// IParseObj
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Entry license;
List<IParseObj> packed_edges;
public Entry License { get { return license; } }
public Tfs Tfs { get { return this; } }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public abstract IList<IDerivation> Derivations { get; }
public int deleted = 0;
public
IParseObj m_next;
public IParseObj Next { get { return m_next; } }
public bool TrySetTail(IParseObj po)
{
return Interlocked.CompareExchange(ref m_next, po, null) == null;
}
public bool TrySetNext(IParseObj po_to_set, IParseObj po_expected)
{
return Interlocked.CompareExchange(ref m_next, po_to_set, po_expected) == po_expected;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void HoistPackingFrom(PassiveEdge pe_old)
{
var _old = pe_old.packed_edges;
if (_old != null)
{
pe_old.packed_edges = null;
if (packed_edges == null)
packed_edges = _old;
else
packed_edges.AddRange(_old);
#if false
PassiveEdge[] defer = null;
int _tmp, c = 0;
foreach (PassiveEdge hoist in _old)
{
if ((_tmp = hoist.TryTransact()) == SequenceControl.ACTIVE)
hoist.s_state = SequenceControl.HOLD;
else if ((_tmp & SequenceControl.stb_Blocked) > 0)
(defer = defer ?? new PassiveEdge[_old.Count])[c++] = hoist;
}
if (defer != null)
{
Console.WriteLine("yabba");
Environment.Exit(0);
int i = -1, rem = c;
do
{
do
if (++i == c)
i = 0;
while (defer[i] == null);
if ((_tmp = defer[i].TryTransact()) == SequenceControl.ACTIVE)
defer[i].SetStateRaw(SequenceControl.HOLD);
else if ((_tmp & SequenceControl.stb_Blocked) > 0)
continue;
defer[i] = null;
}
while (--rem > 0);
}
#else
foreach (PassiveEdge hoist in _old)
if (hoist.BeginTransact())
hoist.s_state = SequenceControl.HOLD;
#endif
}
else
{
if (packed_edges == null)
packed_edges = new List<IParseObj>(12);
}
packed_edges.Add(pe_old);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected IEnumerable<IDerivation> _peer_packed()
{
Debug.Assert(ctrl.f_parse_phase_complete);
Debug.Assert(this.IsActive()); /// ok because parse phase should be complete
#if false
if (packed_edges != null)
foreach (IParseObj parseobj in packed_edges)
{
if (parseobj.IsRemove())
continue;
#if DEBUG
var pt = parseobj as PassiveEdge;
if (pt != null && pt.packed_edges != null)
throw new Exception();
#endif
foreach (IDerivation tree in parseobj.Derivations)
yield return tree;
}
#else
return packed_edges == null ?
Derived.NoDerivations :
packed_edges.Where(ce => !ce.IsRemove()).SelectMany(ce => ce.Derivations);
#endif
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// IAtomicallySequenceable
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int i_seq;
public int SequenceId { get { return i_seq; } }
public void SetSequenceId(int id) { i_seq = id; }
int s_state;
public int State { get { return s_state; } }
public void SetStateRaw(int s) { s_state = s; }
public bool BeginTransact()
{
if ((s_state & (SequenceControl.stb_Hold | SequenceControl.stb_Remove)) > 0)
return false;
SpinWait sw = new SpinWait();
while (true)
{
int q = Interlocked.CompareExchange(ref s_state, SequenceControl.TRANSACT, SequenceControl.ACTIVE);
if (q == SequenceControl.ACTIVE)
return true;
if ((q & (SequenceControl.stb_Hold | SequenceControl.stb_Remove)) > 0)
return false;
sw.SpinOnce();
//Thread.Yield();
}
}
/// <summary>
/// returns:
/// 'SequenceControl.ACTIVE' if the transaction is started
/// </summary>
/// <returns></returns>
public int TryTransact()
{
int _tmp = s_state;
if ((_tmp & (SequenceControl.stb_Hold | SequenceControl.stb_Remove)) > 0)
return _tmp;
return Interlocked.CompareExchange(ref s_state, SequenceControl.TRANSACT, SequenceControl.ACTIVE);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// ISysObj
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public new ISysObj SysObjParent { get { return ctrl; } }
};
}