Introduce IdentifierManager to improve PDT evaluator performance.
This commit is contained in:
@@ -1,66 +1,54 @@
|
||||
using Cryville.Common.Pdt;
|
||||
using Cryville.Common;
|
||||
using Cryville.Common.Pdt;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
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;
|
||||
}
|
||||
}
|
||||
static readonly Dictionary<PdtOperatorSignature, PdtOperator> _shortops = new Dictionary<PdtOperatorSignature, PdtOperator>();
|
||||
static readonly Dictionary<int, PdtOperator> _longops = new Dictionary<int, PdtOperator>();
|
||||
readonly Dictionary<int, PdtOperator> _ctxops = new Dictionary<int, PdtOperator>();
|
||||
|
||||
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;
|
||||
}
|
||||
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");
|
||||
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; }
|
||||
else if (name == _var_true) { LoadNum(1); type = PdtInternalType.Number; value = _numbuf; }
|
||||
else if (name == _var_false) { LoadNum(0); type = PdtInternalType.Number; value = _numbuf; }
|
||||
else {
|
||||
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;
|
||||
type = PdtInternalType.Undefined;
|
||||
LoadNum(name);
|
||||
value = _numbuf;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
unsafe void LoadNum(int value) {
|
||||
fixed (byte* ptr = _numbuf) *(int*)ptr = value;
|
||||
}
|
||||
unsafe void LoadNum(float value) {
|
||||
fixed (byte* ptr = _numbuf) *(float*)ptr = value;
|
||||
}
|
||||
@@ -75,31 +63,32 @@ namespace Cryville.Crtr {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
protected override PdtOperator GetOperator(string name, int pc) {
|
||||
static int _op_sep = IdentifierManager.SharedInstance.Request(",");
|
||||
protected override PdtOperator GetOperator(PdtOperatorSignature sig) {
|
||||
PdtOperator result;
|
||||
if (name.Length == 1 && _shortops.TryGetValue(new OperatorSignature(name, pc), out result)) {
|
||||
if (_shortops.TryGetValue(sig, out result)) {
|
||||
return result;
|
||||
}
|
||||
else if (name == ",") {
|
||||
result = new op_arr(pc);
|
||||
_shortops.Add(new OperatorSignature(",", pc), result);
|
||||
else if (sig.Name == _op_sep) {
|
||||
result = new op_arr(sig.ParamCount);
|
||||
_shortops.Add(new PdtOperatorSignature(",", sig.ParamCount), result);
|
||||
return result;
|
||||
}
|
||||
else if (_longops.TryGetValue(name, out result)) {
|
||||
else if (_longops.TryGetValue(sig.Name, out result)) {
|
||||
return result;
|
||||
}
|
||||
else if (_ctxops.TryGetValue(name, out result)) {
|
||||
else if (_ctxops.TryGetValue(sig.Name, out result)) {
|
||||
return result;
|
||||
}
|
||||
else throw new KeyNotFoundException(string.Format("Undefined operator {0}({1})", name, pc));
|
||||
else throw new KeyNotFoundException(string.Format("Undefined operator {0}", sig));
|
||||
}
|
||||
|
||||
protected override bool Collapse(string name, PdtVariableMemory param) {
|
||||
switch (name) {
|
||||
case "&": return param.AsNumber() == 0;
|
||||
case "|": return param.AsNumber() != 0;
|
||||
default: throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", name));
|
||||
}
|
||||
static int _colop_and = IdentifierManager.SharedInstance.Request("&");
|
||||
static 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;
|
||||
else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", name));
|
||||
}
|
||||
|
||||
public ChartEvent ContextEvent { private get; set; }
|
||||
@@ -107,11 +96,11 @@ namespace Cryville.Crtr {
|
||||
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>>();
|
||||
readonly List<Dictionary<int, PropSrc.Arbitrary>> ContextCascade = new List<Dictionary<int, PropSrc.Arbitrary>>();
|
||||
public void ContextCascadeInsert() {
|
||||
ContextCascade.Add(new Dictionary<string, PropSrc.Arbitrary>());
|
||||
ContextCascade.Add(new Dictionary<int, PropSrc.Arbitrary>());
|
||||
}
|
||||
public void ContextCascadeUpdate(string key, PropSrc.Arbitrary value) {
|
||||
public void ContextCascadeUpdate(int key, PropSrc.Arbitrary value) {
|
||||
ContextCascade[ContextCascade.Count - 1][key] = value;
|
||||
}
|
||||
public void ContextCascadeDiscard() {
|
||||
@@ -119,29 +108,29 @@ namespace Cryville.Crtr {
|
||||
}
|
||||
|
||||
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));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("screen_edge"), new func_screen_edge(() => ContextTransform));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("int"), new func_int(() => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("clamp"), new func_clamp(() => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue));
|
||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
|
||||
}
|
||||
static PdtEvaluator() {
|
||||
_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 PdtOperatorSignature("*", 2), new op_mul_2());
|
||||
_shortops.Add(new PdtOperatorSignature("/", 2), new op_div_2());
|
||||
_shortops.Add(new PdtOperatorSignature("%", 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("-", 1), new op_sub_1());
|
||||
_shortops.Add(new OperatorSignature("-", 2), new op_sub_2());
|
||||
_shortops.Add(new PdtOperatorSignature("+", 1), new op_add_1());
|
||||
_shortops.Add(new PdtOperatorSignature("+", 2), new op_add_2());
|
||||
_shortops.Add(new PdtOperatorSignature("-", 1), new op_sub_1());
|
||||
_shortops.Add(new PdtOperatorSignature("-", 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 PdtOperatorSignature("=", 2), new op_eq_2());
|
||||
_shortops.Add(new PdtOperatorSignature("<", 2), new op_lt_2());
|
||||
_shortops.Add(new PdtOperatorSignature(">", 2), new op_gt_2());
|
||||
|
||||
_shortops.Add(new OperatorSignature("!", 1), new op_not_1());
|
||||
_shortops.Add(new PdtOperatorSignature("!", 1), new op_not_1());
|
||||
|
||||
_longops.Add("frame_seq", new func_frame_seq());
|
||||
_longops.Add(IdentifierManager.SharedInstance.Request("frame_seq"), new func_frame_seq());
|
||||
}
|
||||
#region Operators
|
||||
#pragma warning disable IDE1006
|
||||
|
Reference in New Issue
Block a user