Add "at" operator.

This commit is contained in:
2022-11-05 17:41:54 +08:00
parent 8e3bd87667
commit a422f06221
3 changed files with 35 additions and 13 deletions

View File

@@ -90,6 +90,7 @@ namespace Cryville.Common.Pdt {
}
public partial class PdtInterpreter<T> {
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
{ '@', 7 },
{ '*', 6 }, { '/', 6 }, { '%', 6 },
{ '+', 5 }, { '-', 5 },
{ '=', 4 }, { '<', 4 }, { '>', 4 },
@@ -100,6 +101,7 @@ namespace Cryville.Common.Pdt {
{ '$', -1 },
};
readonly static Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
{ '@', 0 },
{ '*', 0 }, { '/', 0 }, { '%', 0 },
{ '+', 0 }, { '-', 0 },
{ '=', 0 }, { '<', 0 }, { '>', 0 },

View File

@@ -42,28 +42,33 @@ namespace Cryville.Common.Pdt {
/// <summary>
/// Gets the memory of the span as a number.
/// </summary>
/// <param name="offset">The offset on the span to start reading from.</param>
/// <returns>A number.</returns>
/// <exception cref="InvalidCastException">The span does not represent a number.</exception>
public float AsNumber() {
/// <exception cref="InvalidCastException">The span at the offset does not represent a number.</exception>
public float AsNumber(int offset = 0) {
if (Type != PdtInternalType.Number)
throw new InvalidCastException("Not a number");
float value;
byte* ptr = (byte*)&value;
for (int i = 0; i < sizeof(float); i++)
ptr[i] = _ptr[i];
ptr[i] = _ptr[i + offset];
return value;
}
/// <summary>
/// Sets the memory of the span to a number.
/// </summary>
/// <param name="value">The number.</param>
/// <exception cref="InvalidCastException">The span does not represent a number.</exception>
public void SetNumber(float value) {
/// <param name="offset">The offset from the start of the span.</param>
/// <exception cref="InvalidCastException">The span at the offset does not represent a number.</exception>
/// <exception cref="InvalidOperationException">The length of the span is not sufficient.</exception>
public void SetNumber(float value, int offset = 0) {
if (Type != PdtInternalType.Number)
throw new InvalidCastException("Not a number");
if (Length < sizeof(float) + offset)
throw new InvalidOperationException("Frame length not sufficient");
byte* ptr = (byte*)&value;
for (int i = 0; i < sizeof(float); i++)
_ptr[i] = ptr[i];
_ptr[i + offset] = ptr[i];
}
/// <summary>
/// Gets the memory of the span as a string.

View File

@@ -11,10 +11,10 @@ namespace Cryville.Crtr {
readonly Dictionary<int, PdtOperator> _ctxops = new Dictionary<int, PdtOperator>();
readonly byte[] _numbuf = new byte[4];
static int _var_w = IdentifierManager.SharedInstance.Request("w");
static int _var_h = IdentifierManager.SharedInstance.Request("h");
static int _var_true = IdentifierManager.SharedInstance.Request("true");
static int _var_false = IdentifierManager.SharedInstance.Request("false");
static readonly int _var_w = IdentifierManager.SharedInstance.Request("w");
static readonly int _var_h = IdentifierManager.SharedInstance.Request("h");
static readonly int _var_true = IdentifierManager.SharedInstance.Request("true");
static readonly int _var_false = IdentifierManager.SharedInstance.Request("false");
protected override void GetVariable(int name, out int type, out byte[] value) {
if (name == _var_w) { LoadNum(ChartPlayer.hitRect.width); type = PdtInternalType.Number; value = _numbuf; }
else if (name == _var_h) { LoadNum(ChartPlayer.hitRect.height); type = PdtInternalType.Number; value = _numbuf; }
@@ -64,7 +64,7 @@ namespace Cryville.Crtr {
}
return result;
}
static int _op_sep = IdentifierManager.SharedInstance.Request(",");
static readonly int _op_sep = IdentifierManager.SharedInstance.Request(",");
protected override PdtOperator GetOperator(PdtOperatorSignature sig) {
PdtOperator result;
if (_shortops.TryGetValue(sig, out result)) {
@@ -84,8 +84,8 @@ namespace Cryville.Crtr {
else throw new KeyNotFoundException(string.Format("Undefined operator {0}", sig));
}
static int _colop_and = IdentifierManager.SharedInstance.Request("&");
static int _colop_or = IdentifierManager.SharedInstance.Request("|");
static readonly int _colop_and = IdentifierManager.SharedInstance.Request("&");
static readonly int _colop_or = IdentifierManager.SharedInstance.Request("|");
protected override bool Collapse(int name, PdtVariableMemory param) {
if (name == _colop_and) return param.AsNumber() == 0;
else if(name == _colop_or) return param.AsNumber() != 0;
@@ -116,6 +116,8 @@ namespace Cryville.Crtr {
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
}
static PdtEvaluator() {
_shortops.Add(new PdtOperatorSignature("@", 2), new op_at_2());
_shortops.Add(new PdtOperatorSignature("*", 2), new op_mul_2());
_shortops.Add(new PdtOperatorSignature("/", 2), new op_div_2());
_shortops.Add(new PdtOperatorSignature("%", 2), new op_mod_2());
@@ -232,6 +234,19 @@ namespace Cryville.Crtr {
return type == PdtInternalType.Number;
}
}
class op_at_2 : PdtOperator {
public op_at_2() : base(2) { }
protected override void Execute() {
int _, pc;
var op0 = GetOperand(0);
var op1 = (int)Math.Round(GetOperand(1).AsNumber());
if (op0.Type != PdtInternalType.Vector) throw new InvalidOperationException("Not a vector");
op0.GetArraySuffix(out _, out pc);
if (op1 >= pc) throw new IndexOutOfRangeException();
float result = GetOperand(0).AsNumber(op1 * sizeof(float));
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
}
}
class func_frame_seq : PdtOperator {
public func_frame_seq() : base(3) { }
protected override unsafe void Execute() {