using System; namespace Cryville.Common.Pdt { /// /// PDT operator. /// public abstract unsafe class PdtOperator { byte* _prmem; int _loadindex; readonly PdtVariableMemory[] _operands; /// /// The count of the operands loaded. /// protected int LoadedOperandCount { get; private set; } /// /// 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 ArgumentOutOfRangeException("index"); int i = index + _loadindex; return _operands[i]; } readonly int _pc; /// /// Creates an instance of the class. /// /// The suggested parameter count. protected PdtOperator(int pc) { _pc = pc; _operands = new PdtVariableMemory[pc]; } PdtEvaluatorBase _etor; bool _rfreq = true; internal void Begin(PdtEvaluatorBase etor, int pc) { _etor = etor; _loadindex = LoadedOperandCount = pc; } internal void LoadOperand(PdtVariableMemory mem) { if (--_loadindex >= _pc) 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 EvaluationFailureException("Evaluation failed", ex); } if (!_rfreq && !noset) throw new EvaluationFailureException("Return frame not set"); } /// /// Executes the operator. /// /// /// When overridden, this method reads operands by calling , and writes the result to the frame obtained by calling . /// 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) throw new InvalidOperationException("Return frame requested twice"); _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.Shared.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 readonly bool Equals(object obj) { if (obj is not PdtOperatorSignature other) return false; return Equals(other); } public readonly bool Equals(PdtOperatorSignature other) { return Name == other.Name && ParamCount == other.ParamCount; } public override readonly int GetHashCode() { return _hash; } public override readonly string ToString() { return string.Format("{0}({1})", IdentifierManager.Shared.Retrieve(Name), ParamCount); } } }