Allows for overloaded functions in CSharp to be used, initial work on handling CSHarp operators
This commit is contained in:
parent
fe4a8d25ad
commit
0702b9f271
|
@ -13,6 +13,11 @@ namespace Upsilon.BaseTypes
|
|||
return Value;
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return typeof(bool);
|
||||
}
|
||||
|
||||
public bool Value { get; }
|
||||
|
||||
public static implicit operator bool(LuaBoolean b)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Upsilon.BaseTypes.UserData;
|
||||
using Upsilon.Binder;
|
||||
using Upsilon.Evaluator;
|
||||
|
||||
|
@ -14,6 +15,11 @@ namespace Upsilon.BaseTypes
|
|||
return this;
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract LuaType Run(Diagnostics diagnostics, LuaType[] variables);
|
||||
}
|
||||
|
||||
|
@ -46,19 +52,21 @@ namespace Upsilon.BaseTypes
|
|||
|
||||
internal class LuaMethodInfoFunction : LuaFunction
|
||||
{
|
||||
public LuaMethodInfoFunction(MethodInfo method, object o)
|
||||
public LuaMethodInfoFunction(UserDataMethod method, object o)
|
||||
{
|
||||
_method = method;
|
||||
_object = o;
|
||||
}
|
||||
|
||||
private readonly MethodInfo _method;
|
||||
private readonly UserDataMethod _method;
|
||||
private readonly object _object;
|
||||
|
||||
public override LuaType Run(Diagnostics diagnostics, LuaType[] variables)
|
||||
{
|
||||
var types = variables.Select(x => x.GetCSharpType());
|
||||
var method = _method.GetMethod(types.ToArray());
|
||||
var objects = variables.Select(x => x.ToCSharpObject());
|
||||
return _method.Invoke(_object, objects.ToArray()).ToLuaType();
|
||||
return method.Invoke(_object, objects.ToArray()).ToLuaType();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,11 @@ namespace Upsilon.BaseTypes
|
|||
return null;
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "null";
|
||||
|
|
|
@ -19,6 +19,11 @@ namespace Upsilon.BaseTypes
|
|||
return Value;
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return typeof(string);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Upsilon.Binder;
|
||||
using Upsilon.Evaluator;
|
||||
|
@ -21,6 +22,11 @@ namespace Upsilon.BaseTypes
|
|||
return EvaluationScope.Variables.ToDictionary(x => x.Key, x => x.Value.ToCSharpObject());
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return typeof(Dictionary<string, object>);
|
||||
}
|
||||
|
||||
public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
|
||||
{
|
||||
if (EvaluationScope.TryGet(s, out var o))
|
||||
|
|
|
@ -4,5 +4,6 @@ namespace Upsilon.BaseTypes
|
|||
{
|
||||
public abstract Type Type { get; }
|
||||
public abstract object ToCSharpObject();
|
||||
public abstract System.Type GetCSharpType();
|
||||
}
|
||||
}
|
|
@ -31,5 +31,10 @@ namespace Upsilon.BaseTypes.Number
|
|||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return typeof(double);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,5 +34,10 @@ namespace Upsilon.BaseTypes.Number
|
|||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return typeof(long);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,11 @@ namespace Upsilon.BaseTypes.UserData
|
|||
return Value;
|
||||
}
|
||||
|
||||
public override System.Type GetCSharpType()
|
||||
{
|
||||
return Value.GetType();
|
||||
}
|
||||
|
||||
public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
|
||||
{
|
||||
var (type, failed) = _typeInfo.Get(Value, s);
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Upsilon.BaseTypes.UserData
|
||||
{
|
||||
public class UserDataMethod
|
||||
{
|
||||
private class UserDataMethodPart
|
||||
{
|
||||
public UserDataMethodPart(MethodInfo method)
|
||||
{
|
||||
Method = method;
|
||||
Parameters = method.GetParameters().Select(x => new UserDataMethodParameter(x)).ToArray();
|
||||
}
|
||||
|
||||
public MethodInfo Method { get; }
|
||||
public UserDataMethodParameter[] Parameters { get; }
|
||||
}
|
||||
|
||||
private struct UserDataMethodParameter
|
||||
{
|
||||
public UserDataMethodParameter(ParameterInfo info)
|
||||
{
|
||||
TypeHash = info.ParameterType.GetHashCode();
|
||||
IsOptional = info.IsOptional;
|
||||
}
|
||||
|
||||
public int TypeHash { get; }
|
||||
public bool IsOptional { get; }
|
||||
}
|
||||
|
||||
private List<UserDataMethodPart> MethodParts { get; }
|
||||
|
||||
public UserDataMethod(MethodInfo method)
|
||||
{
|
||||
var part = new UserDataMethodPart(method);
|
||||
MethodParts = new List<UserDataMethodPart>()
|
||||
{
|
||||
part
|
||||
};
|
||||
}
|
||||
|
||||
public void LoadMethodPart(MethodInfo method)
|
||||
{
|
||||
var part = new UserDataMethodPart(method);
|
||||
MethodParts.Add(part);
|
||||
}
|
||||
|
||||
public MethodInfo GetMethod(System.Type[] parameterTypes)
|
||||
{
|
||||
foreach (var userDataMethodPart in MethodParts)
|
||||
{
|
||||
bool valid = true;
|
||||
for (var index = 0; index < userDataMethodPart.Parameters.Length; index++)
|
||||
{
|
||||
var userDataMethodParameter = userDataMethodPart.Parameters[index];
|
||||
if (index >= parameterTypes.Length)
|
||||
{
|
||||
if (userDataMethodParameter.IsOptional)
|
||||
return userDataMethodPart.Method;
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
var parameterHash = parameterTypes[index].GetHashCode();
|
||||
if (userDataMethodParameter.TypeHash != parameterHash)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid) return userDataMethodPart.Method;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System.Linq;
|
||||
|
||||
namespace Upsilon.BaseTypes.UserData
|
||||
{
|
||||
public struct UserDataMethodKey
|
||||
{
|
||||
public UserDataMethodKey(string name, System.Type[] parameterTypes)
|
||||
{
|
||||
Name = name;
|
||||
ParameterTypeHashes = parameterTypes.Select(x => x.GetHashCode()).ToArray();
|
||||
}
|
||||
|
||||
public UserDataMethodKey(string name, int[] parameterTypeHashes)
|
||||
{
|
||||
Name = name;
|
||||
ParameterTypeHashes = parameterTypeHashes;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public int[] ParameterTypeHashes { get; }
|
||||
}
|
||||
}
|
|
@ -11,13 +11,27 @@ namespace Upsilon.BaseTypes.UserData
|
|||
Type = type;
|
||||
Variables = type.GetFields().ToDictionary(x => x.Name.ToLowerInvariant(), x => x);
|
||||
Properties = type.GetProperties().ToDictionary(x => x.Name.ToLowerInvariant(), x => x);
|
||||
Methods = type.GetMethods().ToDictionary(x => x.Name.ToLowerInvariant(), x => x);
|
||||
Methods = new Dictionary<string, UserDataMethod>();
|
||||
foreach (var methodInfo in type.GetMethods())
|
||||
{
|
||||
var commonName = methodInfo.Name.ToLowerInvariant();
|
||||
if (Methods.TryGetValue(commonName, out var methodData))
|
||||
{
|
||||
methodData.LoadMethodPart(methodInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Methods.Add(commonName, new UserDataMethod(methodInfo));
|
||||
}
|
||||
}
|
||||
_operatorHandler = new UserDataTypeOperators(type);
|
||||
}
|
||||
|
||||
private System.Type Type { get; }
|
||||
private Dictionary<string, FieldInfo> Variables { get; }
|
||||
private Dictionary<string, PropertyInfo> Properties { get; }
|
||||
private Dictionary<string, MethodInfo> Methods { get; }
|
||||
private Dictionary<string, UserDataMethod> Methods { get; }
|
||||
private UserDataTypeOperators _operatorHandler { get; }
|
||||
|
||||
public (LuaType Type, bool Failed) Get(object value, string member)
|
||||
{
|
||||
|
@ -57,5 +71,10 @@ namespace Upsilon.BaseTypes.UserData
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public (LuaType Type, bool Failed) BinaryOperator(object value, OperatorType op, object value2)
|
||||
{
|
||||
return (null, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Upsilon.BaseTypes.UserData
|
||||
{
|
||||
public enum OperatorType
|
||||
{
|
||||
Addition,
|
||||
}
|
||||
|
||||
public class UserDataTypeOperators
|
||||
{
|
||||
private class OperatorKeyData
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public UserDataTypeOperators(System.Type t)
|
||||
{
|
||||
var additionMethod = t.GetMethod("op_Addition", BindingFlags.Static | BindingFlags.Public);
|
||||
Console.WriteLine(additionMethod);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using Upsilon.Evaluator;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using Upsilon.BaseTypes.UserData;
|
||||
using Upsilon.Evaluator;
|
||||
using Xunit;
|
||||
// ReSharper disable UnusedMember.Local
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
|
||||
namespace UpsilonTests
|
||||
{
|
||||
public class UserDataOperatorTests : IClassFixture<UserDataOperatorTests.UserDataOperatorTestsFixture>
|
||||
{
|
||||
public class UserDataOperatorTestsFixture : IDisposable
|
||||
{
|
||||
public UserDataOperatorTestsFixture()
|
||||
{
|
||||
UserDataTypeHandler.LoadType<UserDataHelper>();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable 414, 649
|
||||
private class UserDataHelper
|
||||
{
|
||||
public UserDataHelper(double value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public double Value { get; }
|
||||
|
||||
public static UserDataHelper operator +(UserDataHelper a, UserDataHelper b)
|
||||
{
|
||||
return new UserDataHelper(a.Value + b.Value);
|
||||
}
|
||||
|
||||
public static UserDataHelper operator +(UserDataHelper a, double b)
|
||||
{
|
||||
return new UserDataHelper(a.Value + b);
|
||||
}
|
||||
|
||||
}
|
||||
#pragma warning restore 414, 649
|
||||
|
||||
|
||||
[Fact]
|
||||
public void TestAddition()
|
||||
{
|
||||
const string input = @"
|
||||
function add(o1, o2)
|
||||
return o1 + o2
|
||||
end
|
||||
";
|
||||
var script = new Script(input);
|
||||
Assert.Empty(script.Diagnostics.Messages);
|
||||
var o1 = new UserDataHelper(100);
|
||||
var o2 = new UserDataHelper(215);
|
||||
var result = script.EvaluateFunction("add", new[] {o1, o2});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue