Implement function overloading
This commit is contained in:
parent
1b32ab921b
commit
1c181442e8
|
@ -121,17 +121,35 @@ namespace PorygonSharp.UserData
|
|||
|
||||
private void RegisterFunction(MethodInfo method)
|
||||
{
|
||||
var type = ScriptType.ScriptTypeHandler.GetFunctionScriptType(method);
|
||||
if (type == IntPtr.Zero || !type.HasValue)
|
||||
return;
|
||||
var fieldName = method.Name.ScriptHash();
|
||||
if (Fields.ContainsKey(fieldName))
|
||||
return;
|
||||
var fieldData = new UserDataField(method);
|
||||
var userDataField = CreateUserDataField(type.Value, fieldData.GetGetterPointer(), IntPtr.Zero);
|
||||
if (Fields.TryGetValue(fieldName, out var f))
|
||||
{
|
||||
if (!(f is UserDataFunctionField func))
|
||||
return;
|
||||
|
||||
var methodPtr = func.MethodPtr;
|
||||
var ret = ScriptType.ScriptTypeHandler.GetScriptType(method.ReturnType);
|
||||
if (!ret.HasValue) return;
|
||||
var parameters = method.GetParameters()
|
||||
.Select(x => ScriptType.ScriptTypeHandler.GetScriptType(x.ParameterType))
|
||||
.ToArray();
|
||||
if (parameters.Any(x => !x.HasValue))
|
||||
return;
|
||||
RegisterUserDataFunctionScriptTypeOption(methodPtr, ret.Value,
|
||||
parameters.Select(x => x.Value).ToArray(), parameters.Length);
|
||||
func.RegisterOption(method);
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = ScriptType.ScriptTypeHandler.GetFunctionScriptType(method);
|
||||
if (type == IntPtr.Zero || !type.HasValue)
|
||||
return;
|
||||
var fieldData = new UserDataFunctionField(method, type.Value);
|
||||
var userDataField = CreateUserDataField(type.Value, fieldData.GetGetterPointer(), IntPtr.Zero);
|
||||
RegisterUserDataField(Id, fieldName, userDataField);
|
||||
Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
RegisterUserDataField(Id, fieldName, userDataField);
|
||||
Fields.Add(fieldName, fieldData);
|
||||
}
|
||||
|
||||
private bool IsCastable(IntPtr scriptTypePtr, bool isExplicit)
|
||||
|
@ -236,6 +254,9 @@ namespace PorygonSharp.UserData
|
|||
[DllImport("PorygonLang", EntryPoint = "AddUserdataBinaryOperation", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void AddUserdataBinaryOperation(uint id, byte kind, IntPtr operation);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "RegisterUserDataFunctionScriptTypeOption", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr RegisterUserDataFunctionScriptTypeOption(IntPtr existing, IntPtr returnType,
|
||||
IntPtr[] parameters, int parameterCount);
|
||||
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.EvalValues;
|
||||
using PorygonSharp.Utilities;
|
||||
|
||||
namespace PorygonSharp.UserData
|
||||
{
|
||||
|
@ -11,11 +9,11 @@ namespace PorygonSharp.UserData
|
|||
{
|
||||
internal delegate IntPtr GetterDelegate(IntPtr ptr);
|
||||
internal delegate void SetterDelegate(IntPtr ptr, IntPtr val);
|
||||
private delegate IntPtr CallerDelegate(IntPtr parent, IntPtr scriptOption,
|
||||
protected delegate IntPtr CallerDelegate(IntPtr parent, IntPtr scriptOption,
|
||||
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]IntPtr[] parameters, int size);
|
||||
|
||||
private readonly GetterDelegate _getter;
|
||||
private readonly SetterDelegate _setter;
|
||||
protected GetterDelegate _getter;
|
||||
protected readonly SetterDelegate _setter;
|
||||
|
||||
public UserDataField(FieldInfo field)
|
||||
{
|
||||
|
@ -58,30 +56,8 @@ namespace PorygonSharp.UserData
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
public UserDataField(MethodInfo method)
|
||||
{
|
||||
var parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
_getter = ptr =>
|
||||
{
|
||||
var func = new CallerDelegate((parent, scriptOptions, parameters, size) =>
|
||||
{
|
||||
|
||||
var evaluatedParameters = new object[size];
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
var eval = new EvalValue(parameters[i]);
|
||||
evaluatedParameters[i] = Caster.Cast(eval, parameterTypes[i]);
|
||||
}
|
||||
|
||||
var parentObj = GCHandle.FromIntPtr(parent).Target;
|
||||
var result = method.Invoke(parentObj, evaluatedParameters);
|
||||
return EvalValueCreator.CreateValue(result).GetPointer();
|
||||
});
|
||||
var funcPtr = Marshal.GetFunctionPointerForDelegate(func);
|
||||
return EvalValueCreator.FunctionEvalValue(funcPtr, ptr).GetPointer();
|
||||
};
|
||||
}
|
||||
|
||||
protected UserDataField(){}
|
||||
|
||||
public UserDataField(GetterDelegate getter, SetterDelegate setter)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.EvalValues;
|
||||
using PorygonSharp.Utilities;
|
||||
|
||||
namespace PorygonSharp.UserData
|
||||
{
|
||||
internal class UserDataFunctionField : UserDataField
|
||||
{
|
||||
public readonly IntPtr MethodPtr;
|
||||
private readonly List<CallerDelegate> _callers;
|
||||
public UserDataFunctionField(MethodInfo method, IntPtr methodPtr)
|
||||
{
|
||||
_getter = ptr =>
|
||||
{
|
||||
var funcPtr = Marshal.GetFunctionPointerForDelegate(_callers[0]);
|
||||
var val = EvalValueCreator.FunctionEvalValue(funcPtr, ptr);
|
||||
for (var i = 1; i < _callers.Count; i++)
|
||||
{
|
||||
funcPtr = Marshal.GetFunctionPointerForDelegate(_callers[i]);
|
||||
RegisterFunctionEvalValueOption(val.GetPointer(), funcPtr, ptr);
|
||||
}
|
||||
return val.GetPointer();
|
||||
};
|
||||
MethodPtr = methodPtr;
|
||||
_callers = new List<CallerDelegate>(){CreateCaller(method)};
|
||||
}
|
||||
|
||||
private CallerDelegate CreateCaller(MethodInfo method)
|
||||
{
|
||||
var parameterTypes = method.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
return (parent, scriptOptions, parameters, size) =>
|
||||
{
|
||||
var evaluatedParameters = new object[size];
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
var eval = new EvalValue(parameters[i]);
|
||||
evaluatedParameters[i] = Caster.Cast(eval, parameterTypes[i]);
|
||||
}
|
||||
|
||||
var parentObj = GCHandle.FromIntPtr(parent).Target;
|
||||
var result = method.Invoke(parentObj, evaluatedParameters);
|
||||
return EvalValueCreator.CreateValue(result).GetPointer();
|
||||
};
|
||||
}
|
||||
|
||||
internal void RegisterOption(MethodInfo method)
|
||||
{
|
||||
_callers.Add(CreateCaller(method));
|
||||
}
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "RegisterFunctionEvalValueOption",CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr RegisterFunctionEvalValueOption(IntPtr val, IntPtr func, IntPtr obj);
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue