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