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;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override System.Type GetCSharpType()
|
||||||
|
{
|
||||||
|
return typeof(bool);
|
||||||
|
}
|
||||||
|
|
||||||
public bool Value { get; }
|
public bool Value { get; }
|
||||||
|
|
||||||
public static implicit operator bool(LuaBoolean b)
|
public static implicit operator bool(LuaBoolean b)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Upsilon.BaseTypes.UserData;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
|
||||||
|
@ -14,6 +15,11 @@ namespace Upsilon.BaseTypes
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override System.Type GetCSharpType()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract LuaType Run(Diagnostics diagnostics, LuaType[] variables);
|
public abstract LuaType Run(Diagnostics diagnostics, LuaType[] variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,19 +52,21 @@ namespace Upsilon.BaseTypes
|
||||||
|
|
||||||
internal class LuaMethodInfoFunction : LuaFunction
|
internal class LuaMethodInfoFunction : LuaFunction
|
||||||
{
|
{
|
||||||
public LuaMethodInfoFunction(MethodInfo method, object o)
|
public LuaMethodInfoFunction(UserDataMethod method, object o)
|
||||||
{
|
{
|
||||||
_method = method;
|
_method = method;
|
||||||
_object = o;
|
_object = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly MethodInfo _method;
|
private readonly UserDataMethod _method;
|
||||||
private readonly object _object;
|
private readonly object _object;
|
||||||
|
|
||||||
public override LuaType Run(Diagnostics diagnostics, LuaType[] variables)
|
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());
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override System.Type GetCSharpType()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return "null";
|
return "null";
|
||||||
|
|
|
@ -19,6 +19,11 @@ namespace Upsilon.BaseTypes
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override System.Type GetCSharpType()
|
||||||
|
{
|
||||||
|
return typeof(string);
|
||||||
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Upsilon.Binder;
|
using Upsilon.Binder;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
@ -21,6 +22,11 @@ namespace Upsilon.BaseTypes
|
||||||
return EvaluationScope.Variables.ToDictionary(x => x.Key, x => x.Value.ToCSharpObject());
|
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)
|
public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
|
||||||
{
|
{
|
||||||
if (EvaluationScope.TryGet(s, out var o))
|
if (EvaluationScope.TryGet(s, out var o))
|
||||||
|
|
|
@ -4,5 +4,6 @@ namespace Upsilon.BaseTypes
|
||||||
{
|
{
|
||||||
public abstract Type Type { get; }
|
public abstract Type Type { get; }
|
||||||
public abstract object ToCSharpObject();
|
public abstract object ToCSharpObject();
|
||||||
|
public abstract System.Type GetCSharpType();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,5 +31,10 @@ namespace Upsilon.BaseTypes.Number
|
||||||
{
|
{
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override System.Type GetCSharpType()
|
||||||
|
{
|
||||||
|
return typeof(double);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,5 +34,10 @@ namespace Upsilon.BaseTypes.Number
|
||||||
{
|
{
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override System.Type GetCSharpType()
|
||||||
|
{
|
||||||
|
return typeof(long);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,6 +20,11 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override System.Type GetCSharpType()
|
||||||
|
{
|
||||||
|
return Value.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
|
public LuaType Get(Diagnostics diagnostics, TextSpan span, string s, EvaluationScope scope)
|
||||||
{
|
{
|
||||||
var (type, failed) = _typeInfo.Get(Value, s);
|
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;
|
Type = type;
|
||||||
Variables = type.GetFields().ToDictionary(x => x.Name.ToLowerInvariant(), x => x);
|
Variables = type.GetFields().ToDictionary(x => x.Name.ToLowerInvariant(), x => x);
|
||||||
Properties = type.GetProperties().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 System.Type Type { get; }
|
||||||
private Dictionary<string, FieldInfo> Variables { get; }
|
private Dictionary<string, FieldInfo> Variables { get; }
|
||||||
private Dictionary<string, PropertyInfo> Properties { 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)
|
public (LuaType Type, bool Failed) Get(object value, string member)
|
||||||
{
|
{
|
||||||
|
@ -57,5 +71,10 @@ namespace Upsilon.BaseTypes.UserData
|
||||||
|
|
||||||
return true;
|
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 Upsilon.Evaluator;
|
||||||
using Xunit;
|
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