using System; namespace Cryville.Common.Pdt { /// /// PDT operator. /// public unsafe abstract class PdtOperator { byte* _prmem; int _loadindex; readonly PdtVariableMemory[] _operands; /// /// The count of the operands loaded. /// protected int LoadedOperandCount { get { return ParamCount - _loadindex; } } /// /// Gets the operand at the specified index. /// /// The index. /// The operand at the specified index. /// is not less than or less than 0. protected PdtVariableMemory GetOperand(int index) { if (index >= LoadedOperandCount || index < 0) throw new IndexOutOfRangeException(); int i = index + _loadindex; return _operands[i]; } internal int ParamCount { get; private set; } /// /// Creates an instance of the class. /// /// The suggested parameter count. protected PdtOperator(int pc) { ParamCount = pc; _operands = new PdtVariableMemory[pc]; } PdtEvaluatorBase _etor; bool _failure = false; bool _rfreq = true; internal void Begin(PdtEvaluatorBase etor) { _etor = etor; _failure = false; _loadindex = ParamCount; } internal void LoadOperand(PdtVariableMemory mem) { if (_loadindex == 0) return; _operands[--_loadindex] = mem; } internal void Call(byte* prmem, bool noset) { _prmem = prmem; _rfreq = false; try { Execute(); } catch (Exception ex) { if (_rfreq) _etor.DiscardStack(); throw new InvalidOperationException("Evaluation failed", ex); } if (_failure) { if (_rfreq) _etor.DiscardStack(); throw new InvalidOperationException("Evaluation failed"); } if (!_rfreq && !noset) throw new InvalidOperationException("Return frame not set"); } /// /// Executes the operator. /// protected abstract void Execute(); /// /// Gets a return frame. /// /// The type of the frame. /// The length of the frame. /// The return frame. /// The return frame has already been requested. protected PdtVariableMemory GetReturnFrame(int type, int len) { if (_rfreq) { _failure = true; throw new InvalidOperationException("Return frame already requested"); } _rfreq = true; return _etor.StackAlloc(type, _prmem, len); } } /// /// The signature of a . /// public struct PdtOperatorSignature : IEquatable { /// /// The name of the operator. /// public int Name { get; private set; } /// /// The parameter count. /// public int ParamCount { get; private set; } readonly int _hash; /// /// Creates an operator signature. /// /// The name of the operator. /// The parameter count. public PdtOperatorSignature(string name, int paramCount) : this(IdentifierManager.SharedInstance.Request(name), paramCount) { } /// /// Creates an operator signature. /// /// The identifier of the operator. /// The parameter count. public PdtOperatorSignature(int name, int paramCount) { Name = name; ParamCount = paramCount; _hash = Name ^ ((ParamCount << 16) | (ParamCount >> 16)); } public override bool Equals(object obj) { if (!(obj is PdtOperatorSignature)) return false; return Equals((PdtOperatorSignature)obj); } public bool Equals(PdtOperatorSignature other) { return Name == other.Name && ParamCount == other.ParamCount; } public override int GetHashCode() { return _hash; } public override string ToString() { return string.Format("{0}({1})", IdentifierManager.SharedInstance.Retrieve(Name), ParamCount); } } }