diff --git a/Assets/Cryville/Common/Pdt/PdtExpression.cs b/Assets/Cryville/Common/Pdt/PdtExpression.cs index 93ff05c..6c8507a 100644 --- a/Assets/Cryville/Common/Pdt/PdtExpression.cs +++ b/Assets/Cryville/Common/Pdt/PdtExpression.cs @@ -90,6 +90,7 @@ namespace Cryville.Common.Pdt { } public partial class PdtInterpreter { readonly static Dictionary OP_PRIORITY = new Dictionary { + { '@', 7 }, { '*', 6 }, { '/', 6 }, { '%', 6 }, { '+', 5 }, { '-', 5 }, { '=', 4 }, { '<', 4 }, { '>', 4 }, @@ -100,6 +101,7 @@ namespace Cryville.Common.Pdt { { '$', -1 }, }; readonly static Dictionary OP_TYPE = new Dictionary { + { '@', 0 }, { '*', 0 }, { '/', 0 }, { '%', 0 }, { '+', 0 }, { '-', 0 }, { '=', 0 }, { '<', 0 }, { '>', 0 }, diff --git a/Assets/Cryville/Common/Pdt/PdtVariableMemory.cs b/Assets/Cryville/Common/Pdt/PdtVariableMemory.cs index 34bc867..99688cf 100644 --- a/Assets/Cryville/Common/Pdt/PdtVariableMemory.cs +++ b/Assets/Cryville/Common/Pdt/PdtVariableMemory.cs @@ -42,28 +42,33 @@ namespace Cryville.Common.Pdt { /// /// Gets the memory of the span as a number. /// + /// The offset on the span to start reading from. /// A number. - /// The span does not represent a number. - public float AsNumber() { + /// The span at the offset does not represent a number. + 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; } /// /// Sets the memory of the span to a number. /// /// The number. - /// The span does not represent a number. - public void SetNumber(float value) { + /// The offset from the start of the span. + /// The span at the offset does not represent a number. + /// The length of the span is not sufficient. + 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]; } /// /// Gets the memory of the span as a string. diff --git a/Assets/Cryville/Crtr/PdtEvaluator.cs b/Assets/Cryville/Crtr/PdtEvaluator.cs index 0796b4d..68cbf3d 100644 --- a/Assets/Cryville/Crtr/PdtEvaluator.cs +++ b/Assets/Cryville/Crtr/PdtEvaluator.cs @@ -11,10 +11,10 @@ namespace Cryville.Crtr { readonly Dictionary _ctxops = new Dictionary(); 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() {