using System;
using System.Collections;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading;
using miew.ReadOnly;
using miew.Tokenization;
namespace agree
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// interface for objects which can be placed into the parse chart. currently, only LexicalAnalysis and
/// (instances which inherit from ParseTfs) DerivedPassiveEdge/CompletedPassiveEdge
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public interface IParseObj : IAtomicSequence, ITokenSpan
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
Entry License { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
Tfs Tfs { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
IList<IDerivation> Derivations { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
IParseObj Next { get; }
bool TrySetTail(IParseObj po);
bool TrySetNext(IParseObj po_to_set, IParseObj po_expected);
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// a specific derivation, more than one of which might be packed into (some implementors of) IParseObj
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public interface IDerivation
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
Tfs UnpackedTfs { get; }
String TreeDisplay();
IParseObj Source { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
ulong DerivationHash { get; }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// for objects that participate in a global atomic sequence
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public interface IAtomicSequence
{
int SequenceId { get; }
void SetSequenceId(int id);
int State { get; }
void SetStateRaw(int s);
bool BeginTransact();
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Extension methods for IAtomicSequence objects
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static class SequenceControl
{
public const int stb_Pending = 0x00;
public const int stb_Active = 0x01;
public const int stb_Hold = 0x02;
public const int stb_Remove = 0x04;
public const int stb_Blocked = unchecked((int)0x80000000);
public const int stb_IdValid = 0x20;
public const int PENDING = stb_Pending | stb_Blocked;
public const int NEW = stb_IdValid | stb_Blocked;
public const int ACTIVE = stb_Active | stb_IdValid;
public const int TRANSACT = stb_Active | stb_IdValid | stb_Blocked;
public const int HOLD = stb_Hold | stb_IdValid;
public const int REMOVE = stb_Remove | stb_IdValid;
public static void SetStateNew(this IAtomicSequence ias_obj)
{
ias_obj.SetStateRaw(NEW);
}
public static void SetStateActive(this IAtomicSequence ias_obj)
{
Debug.Assert((ias_obj.State & (stb_Hold | stb_Remove)) == 0); // cannot re-activate objects
ias_obj.SetStateRaw(ACTIVE);
}
public static bool SeqIdBelow(this IAtomicSequence ias_obj, int upper_id)
{
if ((ias_obj.State & stb_IdValid) == 0)
{
SpinWait sw = new SpinWait();
do
sw.SpinOnce();
while ((ias_obj.State & stb_IdValid) == 0);
}
return ias_obj.SequenceId < upper_id;
}
public static bool SeqIdAbove(this IAtomicSequence ias_obj, int lower_id)
{
if ((ias_obj.State & stb_IdValid) == 0)
{
SpinWait sw = new SpinWait();
do
sw.SpinOnce();
while ((ias_obj.State & stb_IdValid) == 0);
}
return ias_obj.SequenceId > lower_id;
}
public static bool IsActive(this IAtomicSequence ias_obj)
{
int s;
if ((s = ias_obj.State) < 0)
{
SpinWait sw = new SpinWait();
do
sw.SpinOnce();
while ((s = ias_obj.State) < 0);
}
return s == ACTIVE;
}
public static bool IsBlocked(this IAtomicSequence ias_obj)
{
return ias_obj.State < 0;
}
public static void EndTransact(this IAtomicSequence ias_obj, int state)
{
Debug.Assert(ias_obj.State == TRANSACT);
ias_obj.SetStateRaw(state);
}
public static bool IsHold(this IAtomicSequence ias_obj)
{
int s;
if ((s = ias_obj.State) < 0)
{
SpinWait sw = new SpinWait();
do
sw.SpinOnce();
while ((s = ias_obj.State) < 0);
}
return (s & stb_Hold) > 0;
}
public static bool IsHoldOrRemove(this IAtomicSequence ias_obj)
{
int s;
if ((s = ias_obj.State) < 0)
{
SpinWait sw = new SpinWait();
do
sw.SpinOnce();
while ((s = ias_obj.State) < 0);
}
return (s & (stb_Hold | stb_Remove)) > 0;
}
public static bool IsRemove(this IAtomicSequence ias_obj)
{
int s;
if ((s = ias_obj.State) < 0)
{
SpinWait sw = new SpinWait();
do
sw.SpinOnce();
while ((s = ias_obj.State) < 0);
}
return (s & stb_Remove) > 0;
}
public static String ToString(this IAtomicSequence ias_obj)
{
String s = ias_obj.SequenceId.ToString("X");
int b = ias_obj.State;
if ((b & stb_IdValid) > 0)
s += " ID";
if ((b & stb_Blocked) > 0)
s += " BLK";
if ((b & stb_Active) > 0)
s += " ACT";
if ((b & stb_Hold) > 0)
s += " HOLD";
if ((b & stb_Remove) > 0)
s += " REMV";
return s;
}
};
}