Add project files.
This commit is contained in:
373
Assets/Cryville/Crtr/PdtEvaluator.cs
Normal file
373
Assets/Cryville/Crtr/PdtEvaluator.cs
Normal file
@@ -0,0 +1,373 @@
|
||||
using Cryville.Common.Pdt;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SqlTypes;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.Crtr {
|
||||
public class PdtEvaluator : PdtEvaluatorBase {
|
||||
static readonly Dictionary<OperatorSignature, PdtOperator> _shortops = new Dictionary<OperatorSignature, PdtOperator>();
|
||||
static readonly Dictionary<string, PdtOperator> _longops = new Dictionary<string, PdtOperator>();
|
||||
readonly Dictionary<string, PdtOperator> _ctxops = new Dictionary<string, PdtOperator>();
|
||||
struct OperatorSignature : IEquatable<OperatorSignature> {
|
||||
public string Name { get; private set; }
|
||||
public int ParamCount { get; private set; }
|
||||
readonly int _hash;
|
||||
public OperatorSignature(string name, int paramCount) {
|
||||
Name = name;
|
||||
ParamCount = paramCount;
|
||||
_hash = name.GetHashCode() ^ paramCount;
|
||||
}
|
||||
public override bool Equals(object obj) {
|
||||
if (!(obj is OperatorSignature)) return false;
|
||||
return Equals((OperatorSignature)obj);
|
||||
}
|
||||
public bool Equals(OperatorSignature other) {
|
||||
return Name == other.Name && ParamCount == other.ParamCount;
|
||||
}
|
||||
public override int GetHashCode() {
|
||||
return _hash;
|
||||
}
|
||||
}
|
||||
|
||||
readonly byte[] _numbuf = new byte[4];
|
||||
protected override void GetVariable(string name, out int type, out byte[] value) {
|
||||
switch (name) {
|
||||
case "w": LoadNum(ChartPlayer.hitRect.width); type = PdtInternalType.Number; value = _numbuf; return;
|
||||
case "h": LoadNum(ChartPlayer.hitRect.height); type = PdtInternalType.Number; value = _numbuf; return;
|
||||
case "true": LoadNum(1); type = PdtInternalType.Number; value = _numbuf; return;
|
||||
case "false": LoadNum(0); type = PdtInternalType.Number; value = _numbuf; return;
|
||||
default:
|
||||
PropSrc prop;
|
||||
string str;
|
||||
if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) {
|
||||
prop.Get(out type, out value);
|
||||
}
|
||||
else if (ContextJudge != null && ContextJudge.GetFormattedScoreStrings().TryGetValue(name, out str)) {
|
||||
type = PdtInternalType.String;
|
||||
value = GetBytes(str);
|
||||
RevokePotentialConstant();
|
||||
}
|
||||
else {
|
||||
PropSrc.Arbitrary result;
|
||||
foreach (var cas in ContextCascade) {
|
||||
if (cas.TryGetValue(name, out result)) {
|
||||
result.Get(out type, out value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
type = PdtInternalType.Undefined;
|
||||
value = GetBytes(name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
unsafe void LoadNum(float value) {
|
||||
fixed (byte* ptr = _numbuf) *(float*)ptr = value;
|
||||
}
|
||||
unsafe byte[] GetBytes(string value) {
|
||||
int strlen = value.Length;
|
||||
byte[] result = new byte[strlen * sizeof(char) + sizeof(int)];
|
||||
fixed (byte* _ptr = result) {
|
||||
char* ptr = (char*)(_ptr + sizeof(int));
|
||||
*(int*)_ptr = strlen;
|
||||
int i = 0;
|
||||
foreach (var c in value) ptr[i++] = c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
protected override PdtOperator GetOperator(string name, int pc) {
|
||||
PdtOperator result;
|
||||
if (name.Length == 1 && _shortops.TryGetValue(new OperatorSignature(name, pc), out result)) {
|
||||
return result;
|
||||
}
|
||||
else if (name == ",") {
|
||||
result = new op_arr(pc);
|
||||
_shortops.Add(new OperatorSignature(",", pc), result);
|
||||
return result;
|
||||
}
|
||||
else if (_longops.TryGetValue(name, out result)) {
|
||||
return result;
|
||||
}
|
||||
else if (_ctxops.TryGetValue(name, out result)) {
|
||||
return result;
|
||||
}
|
||||
else throw new KeyNotFoundException(string.Format("Undefined operator {0}({1})", name, pc));
|
||||
}
|
||||
|
||||
public ChartEvent ContextEvent { private get; set; }
|
||||
public Transform ContextTransform { private get; set; }
|
||||
public Judge ContextJudge { private get; set; }
|
||||
public PropSrc ContextSelfValue { private get; set; }
|
||||
|
||||
readonly List<Dictionary<string, PropSrc.Arbitrary>> ContextCascade = new List<Dictionary<string, PropSrc.Arbitrary>>();
|
||||
public void ContextCascadeInsert() {
|
||||
ContextCascade.Add(new Dictionary<string, PropSrc.Arbitrary>());
|
||||
}
|
||||
public void ContextCascadeUpdate(string key, PropSrc.Arbitrary value) {
|
||||
ContextCascade[ContextCascade.Count - 1][key] = value;
|
||||
}
|
||||
public void ContextCascadeDiscard() {
|
||||
ContextCascade.RemoveAt(ContextCascade.Count - 1);
|
||||
}
|
||||
|
||||
public PdtEvaluator() {
|
||||
_ctxops.Add("screen_edge", new func_screen_edge(() => ContextTransform));
|
||||
_ctxops.Add("int", new func_int(() => ContextSelfValue));
|
||||
_ctxops.Add("clamp", new func_clamp(() => ContextSelfValue));
|
||||
_ctxops.Add("min", new func_min(() => ContextSelfValue));
|
||||
_ctxops.Add("max", new func_max(() => ContextSelfValue));
|
||||
}
|
||||
static PdtEvaluator() {
|
||||
_shortops.Add(new OperatorSignature("*", 2), new op_mul_2());
|
||||
_shortops.Add(new OperatorSignature("&", 2), new op_mul_2());
|
||||
_shortops.Add(new OperatorSignature("/", 2), new op_div_2());
|
||||
_shortops.Add(new OperatorSignature("%", 2), new op_mod_2());
|
||||
|
||||
_shortops.Add(new OperatorSignature("+", 1), new op_add_1());
|
||||
_shortops.Add(new OperatorSignature("+", 2), new op_add_2());
|
||||
_shortops.Add(new OperatorSignature("|", 2), new op_add_2());
|
||||
_shortops.Add(new OperatorSignature("-", 1), new op_sub_1());
|
||||
_shortops.Add(new OperatorSignature("-", 2), new op_sub_2());
|
||||
|
||||
_shortops.Add(new OperatorSignature("=", 2), new op_eq_2());
|
||||
_shortops.Add(new OperatorSignature("<", 2), new op_lt_2());
|
||||
_shortops.Add(new OperatorSignature(">", 2), new op_gt_2());
|
||||
|
||||
_shortops.Add(new OperatorSignature("!", 1), new op_not_1());
|
||||
|
||||
_longops.Add("frame_seq", new func_frame_seq());
|
||||
}
|
||||
#region Operators
|
||||
#pragma warning disable IDE1006
|
||||
class op_add_1 : PdtOperator {
|
||||
public op_add_1() : base(1) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber();
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_add_2 : PdtOperator {
|
||||
public op_add_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() + GetOperand(1).AsNumber();
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_sub_1 : PdtOperator {
|
||||
public op_sub_1() : base(1) { }
|
||||
protected override void Execute() {
|
||||
float result = -GetOperand(0).AsNumber();
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_sub_2 : PdtOperator {
|
||||
public op_sub_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() - GetOperand(1).AsNumber();
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_mul_2 : PdtOperator {
|
||||
public op_mul_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() * GetOperand(1).AsNumber();
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_div_2 : PdtOperator {
|
||||
public op_div_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() / GetOperand(1).AsNumber();
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_mod_2 : PdtOperator {
|
||||
public op_mod_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() % GetOperand(1).AsNumber();
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_eq_2 : PdtOperator {
|
||||
public op_eq_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() == GetOperand(1).AsNumber() ? 1 : 0;
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_lt_2 : PdtOperator {
|
||||
public op_lt_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() < GetOperand(1).AsNumber() ? 1 : 0;
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_gt_2 : PdtOperator {
|
||||
public op_gt_2() : base(2) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() > GetOperand(1).AsNumber() ? 1 : 0;
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_not_1 : PdtOperator {
|
||||
public op_not_1() : base(1) { }
|
||||
protected override void Execute() {
|
||||
float result = GetOperand(0).AsNumber() == 0 ? 1 : 0;
|
||||
GetReturnFrame(PdtInternalType.Number, sizeof(float)).SetNumber(result);
|
||||
}
|
||||
}
|
||||
class op_arr : PdtOperator {
|
||||
public op_arr(int pc) : base(pc) { }
|
||||
protected override void Execute() {
|
||||
var o0 = GetOperand(0);
|
||||
int type = o0.Type;
|
||||
int len = o0.Length;
|
||||
bool blit = !IsBlittable(type);
|
||||
for (var i = 1; i < ParamCount; i++) {
|
||||
var o = GetOperand(i);
|
||||
if (o.Type != type) throw new InvalidOperationException("Cannot create variant type array");
|
||||
else if (!IsBlittable(o.Type)) blit = true;
|
||||
len += o.Length;
|
||||
}
|
||||
if (blit) GetReturnFrame(PdtInternalType.Array, len + 2 * sizeof(int)).SetArraySuffix(type, ParamCount);
|
||||
else GetReturnFrame(PdtInternalType.Vector, len + sizeof(int)).SetArraySuffix(type);
|
||||
}
|
||||
bool IsBlittable(int type) {
|
||||
return type == PdtInternalType.Number;
|
||||
}
|
||||
}
|
||||
class func_frame_seq : PdtOperator {
|
||||
public func_frame_seq() : base(3) { }
|
||||
protected override unsafe void Execute() {
|
||||
string pf = GetOperand(0).AsString();
|
||||
int f = (int)GetOperand(1).AsNumber();
|
||||
int t = (int)GetOperand(2).AsNumber();
|
||||
int pfl = pf.Length;
|
||||
int fc = t - f + 1;
|
||||
if (fc <= 0) throw new ArgumentException("Start index is greater than end index");
|
||||
int l = (f == 0 ? 1 : 0) + pfl * fc;
|
||||
for (int p = 1, i = 1; p < 4; p++, i *= 10) {
|
||||
int j = i * 10 - 1;
|
||||
if (f <= j && t >= i) {
|
||||
int m = Math.Max(f, i);
|
||||
int n = Math.Min(t, j);
|
||||
l += (n - m + 1) * i;
|
||||
}
|
||||
}
|
||||
l *= sizeof(char);
|
||||
l += sizeof(int) * (fc + 2);
|
||||
var ret = GetReturnFrame(PdtInternalType.Array, l);
|
||||
ret.SetArraySuffix(PdtInternalType.String, fc);
|
||||
int o = 0;
|
||||
for (int i = f; i <= t; i++) {
|
||||
var s = pf + i.ToString();
|
||||
ret.SetString(s, o);
|
||||
o += sizeof(int) + s.Length * sizeof(char);
|
||||
}
|
||||
}
|
||||
}
|
||||
class func_screen_edge : PdtOperator {
|
||||
readonly Func<Transform> _ctxcb;
|
||||
public func_screen_edge(Func<Transform> ctxcb) : base(1) {
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected override unsafe void Execute() {
|
||||
var ctx = _ctxcb();
|
||||
float dist;
|
||||
var ray = new Ray(ctx.position, ctx.rotation * Vector3.forward);
|
||||
ChartPlayer.frustumPlanes[(int)GetOperand(0).AsNumber()].Raycast(ray, out dist);
|
||||
var ret = GetReturnFrame(PdtInternalType.Vector, sizeof(Vector3) + sizeof(int));
|
||||
var ptr = (Vector3*)ret.TrustedAsOfLength(sizeof(Vector3) + sizeof(int));
|
||||
*ptr++ = ray.GetPoint(dist);
|
||||
*(int*)ptr = PdtInternalType.Number;
|
||||
}
|
||||
}
|
||||
class func_int : PdtOperator {
|
||||
readonly Func<PropSrc> _ctxcb;
|
||||
public func_int(Func<PropSrc> ctxcb) : base(1) {
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected override unsafe void Execute() {
|
||||
var ret = GetReturnFrame(PdtInternalType.Number, sizeof(float));
|
||||
float v;
|
||||
switch (LoadedOperandCount) {
|
||||
case 0: v = oputil.AsNumber(_ctxcb()); break;
|
||||
case 1: v = GetOperand(0).AsNumber(); break;
|
||||
default: throw new ArgumentException("Argument count not 0 or 1");
|
||||
}
|
||||
ret.SetNumber(Mathf.Floor(v));
|
||||
}
|
||||
}
|
||||
class func_clamp : PdtOperator {
|
||||
readonly Func<PropSrc> _ctxcb;
|
||||
public func_clamp(Func<PropSrc> ctxcb) : base(3) {
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected override unsafe void Execute() {
|
||||
var ret = GetReturnFrame(PdtInternalType.Number, sizeof(float));
|
||||
float min = GetOperand(0).AsNumber();
|
||||
float value, max;
|
||||
switch (LoadedOperandCount) {
|
||||
case 2:
|
||||
value = oputil.AsNumber(_ctxcb());
|
||||
max = GetOperand(1).AsNumber();
|
||||
break;
|
||||
case 3:
|
||||
value = GetOperand(1).AsNumber();
|
||||
max = GetOperand(2).AsNumber();
|
||||
break;
|
||||
default: throw new ArgumentException("Argument count not 2 or 3");
|
||||
}
|
||||
ret.SetNumber(Mathf.Clamp(value, min, max));
|
||||
}
|
||||
}
|
||||
class func_min : PdtOperator {
|
||||
readonly Func<PropSrc> _ctxcb;
|
||||
public func_min(Func<PropSrc> ctxcb) : base(2) {
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected override unsafe void Execute() {
|
||||
var ret = GetReturnFrame(PdtInternalType.Number, sizeof(float));
|
||||
float a = GetOperand(0).AsNumber();
|
||||
float b;
|
||||
switch (LoadedOperandCount) {
|
||||
case 1: b = oputil.AsNumber(_ctxcb()); break;
|
||||
case 2: b = GetOperand(1).AsNumber(); break;
|
||||
default: throw new ArgumentException("Argument count not 2 or 3");
|
||||
}
|
||||
ret.SetNumber(Mathf.Min(a, b));
|
||||
}
|
||||
}
|
||||
class func_max : PdtOperator {
|
||||
readonly Func<PropSrc> _ctxcb;
|
||||
public func_max(Func<PropSrc> ctxcb) : base(2) {
|
||||
_ctxcb = ctxcb;
|
||||
}
|
||||
protected override unsafe void Execute() {
|
||||
var ret = GetReturnFrame(PdtInternalType.Number, sizeof(float));
|
||||
var a = GetOperand(0).AsNumber();
|
||||
float b;
|
||||
switch (LoadedOperandCount) {
|
||||
case 1: b = oputil.AsNumber(_ctxcb()); break;
|
||||
case 2: b = GetOperand(1).AsNumber(); break;
|
||||
default: throw new ArgumentException("Argument count not 2 or 3");
|
||||
}
|
||||
ret.SetNumber(Mathf.Max(a, b));
|
||||
}
|
||||
}
|
||||
unsafe static class oputil {
|
||||
public static float AsNumber(PropSrc src) {
|
||||
int type; byte[] value;
|
||||
src.Get(out type, out value);
|
||||
if (type != PdtInternalType.Number)
|
||||
throw new ArgumentException("Not a number");
|
||||
fixed (byte* ptr = value) {
|
||||
return *(float*)ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore IDE1006
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user