Add project files.
This commit is contained in:
77
Assets/Cryville/Common/Pdt/PdtOperator.cs
Normal file
77
Assets/Cryville/Common/Pdt/PdtOperator.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
|
||||
namespace Cryville.Common.Pdt {
|
||||
/// <summary>
|
||||
/// PDT operator.
|
||||
/// </summary>
|
||||
public unsafe abstract class PdtOperator {
|
||||
byte* _prmem;
|
||||
int _loadindex;
|
||||
readonly PdtVariableMemory[] _operands;
|
||||
/// <summary>
|
||||
/// The count of the operands loaded.
|
||||
/// </summary>
|
||||
protected int LoadedOperandCount { get { return ParamCount - _loadindex; } }
|
||||
/// <summary>
|
||||
/// Gets the operand at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index.</param>
|
||||
/// <returns>The operand at the specified index.</returns>
|
||||
/// <exception cref="IndexOutOfRangeException"><paramref name="index" /> is not less than <see cref="LoadedOperandCount" /> or less than 0.</exception>
|
||||
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; }
|
||||
/// <summary>
|
||||
/// Creates an instance of the <see cref="PdtOperator" /> class.
|
||||
/// </summary>
|
||||
/// <param name="pc">The suggested parameter count.</param>
|
||||
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;
|
||||
Execute();
|
||||
if (!_rfreq && !noset) throw new InvalidOperationException("Return frame not set");
|
||||
if (_failure) {
|
||||
if (_rfreq) _etor.DiscardStack();
|
||||
throw new InvalidOperationException("Evaluation failed");
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Executes the operator.
|
||||
/// </summary>
|
||||
protected abstract void Execute();
|
||||
/// <summary>
|
||||
/// Gets a return frame.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the frame.</param>
|
||||
/// <param name="len">The length of the frame.</param>
|
||||
/// <returns>The return frame.</returns>
|
||||
/// <exception cref="InvalidOperationException">The return frame has already been requested.</exception>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user