Support for turning delegates into script functions
This commit is contained in:
parent
6402746101
commit
8d16c1fb35
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.Utilities;
|
||||
|
||||
namespace PorygonSharp.EvalValues
|
||||
{
|
||||
public class DelegateEvalValue
|
||||
{
|
||||
private delegate IntPtr InvokeDelegate(IntPtr _, IntPtr options,
|
||||
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]IntPtr[] parameters, int parameterCount);
|
||||
|
||||
private readonly Delegate _delegate;
|
||||
private readonly InvokeDelegate _handler;
|
||||
public readonly IntPtr Pointer;
|
||||
|
||||
public DelegateEvalValue(Delegate del)
|
||||
{
|
||||
_delegate = del;
|
||||
_handler = Invoke;
|
||||
var funcPtr = Marshal.GetFunctionPointerForDelegate(_handler);
|
||||
Pointer = EvalValueCreator.CreateFunctionEvalValue(funcPtr, IntPtr.Zero);
|
||||
}
|
||||
|
||||
private IntPtr Invoke(IntPtr _, IntPtr options, IntPtr[] parPtrs, int parameterCount)
|
||||
{
|
||||
var parameters = new object[parameterCount];
|
||||
var parametersTypes = _delegate.Method.GetParameters().Select(x => x.ParameterType).ToArray();
|
||||
for (var i = 0; i < parameterCount; i++)
|
||||
{
|
||||
var val = new EvalValue(parPtrs[i]);
|
||||
parameters[i] = Caster.Cast(val, parametersTypes[i]);
|
||||
}
|
||||
|
||||
var result = _delegate.DynamicInvoke(parameters);
|
||||
return EvalValueCreator.CreateValue(result).GetPointer();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.UserData;
|
||||
|
||||
|
@ -43,6 +42,10 @@ namespace PorygonSharp.EvalValues
|
|||
case TypeCode.Object:
|
||||
if (typeof(IList).IsAssignableFrom(type))
|
||||
return CreateListEvalValue((IList)o, type);
|
||||
if (typeof(Delegate).IsAssignableFrom(type))
|
||||
{
|
||||
return CreateDelegateEvalValue((Delegate) o);
|
||||
}
|
||||
if (!UserDataHandler.IsTypeRegistered(type) && !UserDataHandler.TryResolveType(type))
|
||||
{
|
||||
throw new Exception($"Type is not registered for use: {type.FullName}");
|
||||
|
@ -68,8 +71,14 @@ namespace PorygonSharp.EvalValues
|
|||
return new EvalValue(ptr);
|
||||
}
|
||||
|
||||
private static EvalValue CreateDelegateEvalValue(Delegate del)
|
||||
{
|
||||
var val = new DelegateEvalValue(del);
|
||||
return new EvalValue(val.Pointer);
|
||||
}
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateNilEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr CreateNilEvalValue();
|
||||
private static extern IntPtr CreateNilEvalValue();
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateIntegerEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
||||
internal static extern IntPtr CreateIntegerEvalValue(long l);
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateFloatEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
||||
|
@ -82,7 +91,7 @@ namespace PorygonSharp.EvalValues
|
|||
private static extern IntPtr CreateUserDataEvalValue(uint typeHash, IntPtr obj);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateFunctionEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateFunctionEvalValue(IntPtr func, IntPtr parent);
|
||||
internal static extern IntPtr CreateFunctionEvalValue(IntPtr func, IntPtr parent);
|
||||
|
||||
[DllImport("PorygonLang", EntryPoint = "CreateCollectionValue", CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern IntPtr CreateCollectionValue(IntPtr type, IntPtr parent, IntPtr getter, IntPtr setter,
|
||||
|
|
|
@ -10,6 +10,10 @@ namespace PorygonSharp.ScriptType
|
|||
{
|
||||
internal static IntPtr? GetScriptType(Type t)
|
||||
{
|
||||
if (t == null)
|
||||
{
|
||||
return CreateScriptType(TypeClass.Nil);
|
||||
}
|
||||
if (t.IsEnum && !t.IsGenericParameter)
|
||||
{
|
||||
if (UserDataHandler.IsTypeRegistered(t))
|
||||
|
@ -42,6 +46,10 @@ namespace PorygonSharp.ScriptType
|
|||
{
|
||||
return CreateScriptType(TypeClass.Nil);
|
||||
}
|
||||
if (t == typeof(object))
|
||||
{
|
||||
return CreateScriptType(TypeClass.Any);
|
||||
}
|
||||
if (UserDataHandler.IsTypeRegistered(t))
|
||||
{
|
||||
return UserDataHandler.CreateUserDataType(t);
|
||||
|
@ -55,6 +63,11 @@ namespace PorygonSharp.ScriptType
|
|||
return CreateUserDataDictionaryType(t);
|
||||
}
|
||||
|
||||
if (typeof(Delegate).IsAssignableFrom(t))
|
||||
{
|
||||
return GetFunctionScriptType(t.GetMethod("Invoke"));
|
||||
}
|
||||
|
||||
var attr = t.GetCustomAttribute<Attributes.PorygonUserdataAttribute>();
|
||||
if (attr != null)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.EvalValues;
|
||||
using PorygonSharp.Utilities;
|
||||
|
@ -7,14 +8,16 @@ namespace PorygonSharp
|
|||
{
|
||||
public static class StaticScope
|
||||
{
|
||||
private static List<object> _variables = new List<object>();
|
||||
public static void RegisterStaticVariable(string name, object o)
|
||||
{
|
||||
var type = o.GetType();
|
||||
var scriptType = ScriptType.ScriptTypeHandler.GetScriptType(type);
|
||||
var hash = name.ScriptHash();
|
||||
var value = EvalValueCreator.CreateValue(o);
|
||||
if (!scriptType.HasValue)
|
||||
return;
|
||||
var hash = name.ScriptHash();
|
||||
var value = EvalValueCreator.CreateValue(o);
|
||||
_variables.Add(o);
|
||||
RegisterStaticVariable(hash, scriptType.Value, value.GetPointer());
|
||||
}
|
||||
|
||||
|
|
|
@ -10,5 +10,6 @@ namespace PorygonSharp
|
|||
Function,
|
||||
UserData,
|
||||
Table,
|
||||
Any
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.EvalValues;
|
||||
using PorygonSharp.Utilities;
|
||||
|
||||
namespace PorygonSharp.UserData
|
||||
{
|
||||
|
@ -38,17 +39,7 @@ namespace PorygonSharp.UserData
|
|||
{
|
||||
var a = GCHandle.FromIntPtr(objectPtr).Target;
|
||||
var b = new EvalValue(variable);
|
||||
var bVal = b.GetObjectValue();
|
||||
if (_parameterType.IsEnum)
|
||||
{
|
||||
var baseType = _parameterType.GetEnumUnderlyingType();
|
||||
bVal = Convert.ChangeType(bVal, baseType);
|
||||
}
|
||||
else if (bVal is IConvertible)
|
||||
{
|
||||
var convertedType = Convert.ChangeType(bVal, _parameterType);
|
||||
bVal = convertedType;
|
||||
}
|
||||
var bVal = Caster.Cast(b, _parameterType);
|
||||
var o = _info.Invoke(null, new[] {a, bVal});
|
||||
return EvalValueCreator.CreateValue(o).GetPointer();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using PorygonSharp.EvalValues;
|
||||
using PorygonSharp.Utilities;
|
||||
|
||||
namespace PorygonSharp.UserData
|
||||
{
|
||||
|
@ -70,22 +71,7 @@ namespace PorygonSharp.UserData
|
|||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
var eval = new EvalValue(parameters[i]);
|
||||
var val = eval.GetObjectValue();
|
||||
var desiredType = parameterTypes[i];
|
||||
if (desiredType.IsEnum)
|
||||
{
|
||||
var baseType = desiredType.GetEnumUnderlyingType();
|
||||
evaluatedParameters[i] = Convert.ChangeType(val, baseType);
|
||||
}
|
||||
else if (val is IConvertible)
|
||||
{
|
||||
var convertedType = Convert.ChangeType(val, desiredType);
|
||||
evaluatedParameters[i] = convertedType;
|
||||
}
|
||||
else
|
||||
{
|
||||
evaluatedParameters[i] = val;
|
||||
}
|
||||
evaluatedParameters[i] = Caster.Cast(eval, parameterTypes[i]);
|
||||
}
|
||||
|
||||
var parentObj = GCHandle.FromIntPtr(parent).Target;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using PorygonSharp.EvalValues;
|
||||
|
||||
namespace PorygonSharp.Utilities
|
||||
{
|
||||
public static class Caster
|
||||
{
|
||||
public static object Cast(EvalValue val, Type t)
|
||||
{
|
||||
var eval = val.GetObjectValue();
|
||||
if (t.IsEnum)
|
||||
{
|
||||
var underlying = t.GetEnumUnderlyingType();
|
||||
return Convert.ChangeType(eval, underlying);
|
||||
}
|
||||
if (eval is IConvertible)
|
||||
{
|
||||
return Convert.ChangeType(eval, t);
|
||||
}
|
||||
return eval;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue