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;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using PorygonSharp.UserData;
|
using PorygonSharp.UserData;
|
||||||
|
|
||||||
|
@ -43,6 +42,10 @@ namespace PorygonSharp.EvalValues
|
||||||
case TypeCode.Object:
|
case TypeCode.Object:
|
||||||
if (typeof(IList).IsAssignableFrom(type))
|
if (typeof(IList).IsAssignableFrom(type))
|
||||||
return CreateListEvalValue((IList)o, type);
|
return CreateListEvalValue((IList)o, type);
|
||||||
|
if (typeof(Delegate).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
return CreateDelegateEvalValue((Delegate) o);
|
||||||
|
}
|
||||||
if (!UserDataHandler.IsTypeRegistered(type) && !UserDataHandler.TryResolveType(type))
|
if (!UserDataHandler.IsTypeRegistered(type) && !UserDataHandler.TryResolveType(type))
|
||||||
{
|
{
|
||||||
throw new Exception($"Type is not registered for use: {type.FullName}");
|
throw new Exception($"Type is not registered for use: {type.FullName}");
|
||||||
|
@ -67,9 +70,15 @@ namespace PorygonSharp.EvalValues
|
||||||
helper.GetIteratorPtr, helper.GetLengthPtr);
|
helper.GetIteratorPtr, helper.GetLengthPtr);
|
||||||
return new EvalValue(ptr);
|
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)]
|
[DllImport("PorygonLang", EntryPoint = "CreateNilEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
||||||
internal static extern IntPtr CreateNilEvalValue();
|
private static extern IntPtr CreateNilEvalValue();
|
||||||
[DllImport("PorygonLang", EntryPoint = "CreateIntegerEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("PorygonLang", EntryPoint = "CreateIntegerEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
||||||
internal static extern IntPtr CreateIntegerEvalValue(long l);
|
internal static extern IntPtr CreateIntegerEvalValue(long l);
|
||||||
[DllImport("PorygonLang", EntryPoint = "CreateFloatEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("PorygonLang", EntryPoint = "CreateFloatEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
@ -82,7 +91,7 @@ namespace PorygonSharp.EvalValues
|
||||||
private static extern IntPtr CreateUserDataEvalValue(uint typeHash, IntPtr obj);
|
private static extern IntPtr CreateUserDataEvalValue(uint typeHash, IntPtr obj);
|
||||||
|
|
||||||
[DllImport("PorygonLang", EntryPoint = "CreateFunctionEvalValue",CallingConvention = CallingConvention.Cdecl)]
|
[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)]
|
[DllImport("PorygonLang", EntryPoint = "CreateCollectionValue", CallingConvention = CallingConvention.Cdecl)]
|
||||||
private static extern IntPtr CreateCollectionValue(IntPtr type, IntPtr parent, IntPtr getter, IntPtr setter,
|
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)
|
internal static IntPtr? GetScriptType(Type t)
|
||||||
{
|
{
|
||||||
|
if (t == null)
|
||||||
|
{
|
||||||
|
return CreateScriptType(TypeClass.Nil);
|
||||||
|
}
|
||||||
if (t.IsEnum && !t.IsGenericParameter)
|
if (t.IsEnum && !t.IsGenericParameter)
|
||||||
{
|
{
|
||||||
if (UserDataHandler.IsTypeRegistered(t))
|
if (UserDataHandler.IsTypeRegistered(t))
|
||||||
|
@ -42,6 +46,10 @@ namespace PorygonSharp.ScriptType
|
||||||
{
|
{
|
||||||
return CreateScriptType(TypeClass.Nil);
|
return CreateScriptType(TypeClass.Nil);
|
||||||
}
|
}
|
||||||
|
if (t == typeof(object))
|
||||||
|
{
|
||||||
|
return CreateScriptType(TypeClass.Any);
|
||||||
|
}
|
||||||
if (UserDataHandler.IsTypeRegistered(t))
|
if (UserDataHandler.IsTypeRegistered(t))
|
||||||
{
|
{
|
||||||
return UserDataHandler.CreateUserDataType(t);
|
return UserDataHandler.CreateUserDataType(t);
|
||||||
|
@ -55,6 +63,11 @@ namespace PorygonSharp.ScriptType
|
||||||
return CreateUserDataDictionaryType(t);
|
return CreateUserDataDictionaryType(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof(Delegate).IsAssignableFrom(t))
|
||||||
|
{
|
||||||
|
return GetFunctionScriptType(t.GetMethod("Invoke"));
|
||||||
|
}
|
||||||
|
|
||||||
var attr = t.GetCustomAttribute<Attributes.PorygonUserdataAttribute>();
|
var attr = t.GetCustomAttribute<Attributes.PorygonUserdataAttribute>();
|
||||||
if (attr != null)
|
if (attr != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using PorygonSharp.EvalValues;
|
using PorygonSharp.EvalValues;
|
||||||
using PorygonSharp.Utilities;
|
using PorygonSharp.Utilities;
|
||||||
|
@ -7,14 +8,16 @@ namespace PorygonSharp
|
||||||
{
|
{
|
||||||
public static class StaticScope
|
public static class StaticScope
|
||||||
{
|
{
|
||||||
|
private static List<object> _variables = new List<object>();
|
||||||
public static void RegisterStaticVariable(string name, object o)
|
public static void RegisterStaticVariable(string name, object o)
|
||||||
{
|
{
|
||||||
var type = o.GetType();
|
var type = o.GetType();
|
||||||
var scriptType = ScriptType.ScriptTypeHandler.GetScriptType(type);
|
var scriptType = ScriptType.ScriptTypeHandler.GetScriptType(type);
|
||||||
var hash = name.ScriptHash();
|
|
||||||
var value = EvalValueCreator.CreateValue(o);
|
|
||||||
if (!scriptType.HasValue)
|
if (!scriptType.HasValue)
|
||||||
return;
|
return;
|
||||||
|
var hash = name.ScriptHash();
|
||||||
|
var value = EvalValueCreator.CreateValue(o);
|
||||||
|
_variables.Add(o);
|
||||||
RegisterStaticVariable(hash, scriptType.Value, value.GetPointer());
|
RegisterStaticVariable(hash, scriptType.Value, value.GetPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,5 +10,6 @@ namespace PorygonSharp
|
||||||
Function,
|
Function,
|
||||||
UserData,
|
UserData,
|
||||||
Table,
|
Table,
|
||||||
|
Any
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using PorygonSharp.EvalValues;
|
using PorygonSharp.EvalValues;
|
||||||
|
using PorygonSharp.Utilities;
|
||||||
|
|
||||||
namespace PorygonSharp.UserData
|
namespace PorygonSharp.UserData
|
||||||
{
|
{
|
||||||
|
@ -38,17 +39,7 @@ namespace PorygonSharp.UserData
|
||||||
{
|
{
|
||||||
var a = GCHandle.FromIntPtr(objectPtr).Target;
|
var a = GCHandle.FromIntPtr(objectPtr).Target;
|
||||||
var b = new EvalValue(variable);
|
var b = new EvalValue(variable);
|
||||||
var bVal = b.GetObjectValue();
|
var bVal = Caster.Cast(b, _parameterType);
|
||||||
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 o = _info.Invoke(null, new[] {a, bVal});
|
var o = _info.Invoke(null, new[] {a, bVal});
|
||||||
return EvalValueCreator.CreateValue(o).GetPointer();
|
return EvalValueCreator.CreateValue(o).GetPointer();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using PorygonSharp.EvalValues;
|
using PorygonSharp.EvalValues;
|
||||||
|
using PorygonSharp.Utilities;
|
||||||
|
|
||||||
namespace PorygonSharp.UserData
|
namespace PorygonSharp.UserData
|
||||||
{
|
{
|
||||||
|
@ -70,22 +71,7 @@ namespace PorygonSharp.UserData
|
||||||
for (var i = 0; i < size; i++)
|
for (var i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
var eval = new EvalValue(parameters[i]);
|
var eval = new EvalValue(parameters[i]);
|
||||||
var val = eval.GetObjectValue();
|
evaluatedParameters[i] = Caster.Cast(eval, parameterTypes[i]);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var parentObj = GCHandle.FromIntPtr(parent).Target;
|
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