Upsilon/Upsilon/BaseTypes/UserData/UserDataTypeOperators.cs

125 lines
4.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Upsilon.BaseTypes.UserData
{
public enum OperatorType
{
UnaryPlus,
UnaryNegation,
LogicalNot,
Addition,
Subtraction,
Multiplication,
Division,
Modulo
}
public class UserDataTypeOperators
{
private class OperatorMethod
{
public MethodInfo Info { get; }
public int[] ParameterTypeHashes { get; }
public OperatorMethod(MethodInfo info)
{
Info = info;
ParameterTypeHashes = info.GetParameters().Select(x => x.ParameterType.GetHashCode()).ToArray();
}
}
private readonly Dictionary<OperatorType, List<OperatorMethod>> _operatorMethods;
public UserDataTypeOperators(IReflect t)
{
var staticMethod = t.GetMethods(BindingFlags.Static | BindingFlags.Public);
_operatorMethods = new Dictionary<OperatorType, List<OperatorMethod>>();
foreach (var methodInfo in staticMethod)
{
switch (methodInfo.Name)
{
// Unary
case "op_UnaryPlus":
LoadMethod(OperatorType.UnaryPlus, methodInfo);
break;
case "op_UnaryNegation":
LoadMethod(OperatorType.UnaryNegation, methodInfo);
break;
case "op_LogicalNot":
LoadMethod(OperatorType.LogicalNot, methodInfo);
break;
// Binary
case "op_Addition":
LoadMethod(OperatorType.Addition, methodInfo);
break;
case "op_Subtraction":
LoadMethod(OperatorType.Subtraction, methodInfo);
break;
case "op_Multiply":
LoadMethod(OperatorType.Multiplication, methodInfo);
break;
case "op_Division":
LoadMethod(OperatorType.Division, methodInfo);
break;
case "op_Modulus":
LoadMethod(OperatorType.Modulo, methodInfo);
break;
}
}
}
private void LoadMethod(OperatorType type, MethodInfo method)
{
if (_operatorMethods.TryGetValue(type, out var ls))
{
ls.Add(new OperatorMethod(method));
}
else
{
_operatorMethods.Add(type, new List<OperatorMethod>(){new OperatorMethod(method)});
}
}
public MethodInfo GetBinaryOperator(OperatorType op, System.Type t1, System.Type t2)
{
if (!_operatorMethods.TryGetValue(op, out var m))
{
return null;
}
if (t1.IsGenericType) t1 = t1.GetGenericTypeDefinition();
if (t2.IsGenericType) t2 = t2.GetGenericTypeDefinition();
foreach (var operatorMethod in m)
{
if (operatorMethod.ParameterTypeHashes[0] == t1.GetHashCode() &&
operatorMethod.ParameterTypeHashes[1] == t2.GetHashCode())
return operatorMethod.Info;
if (operatorMethod.ParameterTypeHashes[1] == t2.GetHashCode() &&
operatorMethod.ParameterTypeHashes[0] == t1.GetHashCode())
return operatorMethod.Info;
}
return null;
}
public MethodInfo GetUnaryOperator(OperatorType op, System.Type t1)
{
if (!_operatorMethods.TryGetValue(op, out var m))
{
return null;
}
foreach (var operatorMethod in m)
{
if (operatorMethod.ParameterTypeHashes[0] == t1.GetHashCode())
return operatorMethod.Info;
}
return null;
}
}
}