Large amount of fixes and improvements
This commit is contained in:
parent
6ecbfe2074
commit
ef2a514e54
|
@ -11,7 +11,7 @@ namespace PorygonSharp.EvalValues
|
||||||
public static EvalValue CreateValue(object o)
|
public static EvalValue CreateValue(object o)
|
||||||
{
|
{
|
||||||
var type = o.GetType();
|
var type = o.GetType();
|
||||||
if (type.IsEnum)
|
if (type.IsEnum && !type.IsGenericParameter)
|
||||||
{
|
{
|
||||||
var typeHash = UserDataHandler.GetTypeId(type);
|
var typeHash = UserDataHandler.GetTypeId(type);
|
||||||
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
||||||
|
@ -41,6 +41,8 @@ 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 (!UserDataHandler.IsTypeRegistered(type))
|
||||||
|
return null;
|
||||||
var typeHash = UserDataHandler.GetTypeId(type);
|
var typeHash = UserDataHandler.GetTypeId(type);
|
||||||
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
||||||
return new EvalValue(CreateUserDataEvalValue(typeHash, GCHandle.ToIntPtr(handle)));
|
return new EvalValue(CreateUserDataEvalValue(typeHash, GCHandle.ToIntPtr(handle)));
|
||||||
|
|
|
@ -10,5 +10,4 @@
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -43,23 +43,43 @@ namespace PorygonSharp
|
||||||
|
|
||||||
private Diagnostics _diagnostics;
|
private Diagnostics _diagnostics;
|
||||||
public Diagnostics Diagnostics => _diagnostics ?? (_diagnostics = new Diagnostics(_internalScript.Diagnostics));
|
public Diagnostics Diagnostics => _diagnostics ?? (_diagnostics = new Diagnostics(_internalScript.Diagnostics));
|
||||||
|
public bool HasErrors => Diagnostics.HasErrors();
|
||||||
|
|
||||||
private static readonly RuntimeTypeHandle SetupHandle = typeof(CoreSetup).TypeHandle;
|
private static readonly RuntimeTypeHandle SetupHandle = typeof(CoreSetup).TypeHandle;
|
||||||
|
|
||||||
public Script(string s)
|
public Script(string s, ScriptOptions options = null)
|
||||||
{
|
{
|
||||||
// Ensure core setup has been called
|
// Ensure core setup has been called
|
||||||
RuntimeHelpers.RunClassConstructor(SetupHandle);
|
RuntimeHelpers.RunClassConstructor(SetupHandle);
|
||||||
|
|
||||||
_internalScriptHandle = Create(s);
|
var optionsPointer = options?.GetRawPointer() ?? IntPtr.Zero;
|
||||||
|
_internalScriptHandle = Create(s, optionsPointer);
|
||||||
_internalScript = Marshal.PtrToStructure<InternalScript>(_internalScriptHandle);
|
_internalScript = Marshal.PtrToStructure<InternalScript>(_internalScriptHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Script(IntPtr ptr)
|
||||||
|
{
|
||||||
|
_internalScriptHandle = ptr;
|
||||||
|
_internalScript = Marshal.PtrToStructure<InternalScript>(_internalScriptHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Script Clone(Script script)
|
||||||
|
{
|
||||||
|
// Ensure core setup has been called
|
||||||
|
RuntimeHelpers.RunClassConstructor(SetupHandle);
|
||||||
|
return new Script(CloneScript(script._internalScriptHandle));
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(_internalScriptHandle);
|
Marshal.FreeHGlobal(_internalScriptHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal IntPtr GetRawPointer()
|
||||||
|
{
|
||||||
|
return _internalScriptHandle;
|
||||||
|
}
|
||||||
|
|
||||||
public EvalValue Evaluate()
|
public EvalValue Evaluate()
|
||||||
{
|
{
|
||||||
var ptr = Evaluate(_internalScriptHandle);
|
var ptr = Evaluate(_internalScriptHandle);
|
||||||
|
@ -108,7 +128,7 @@ namespace PorygonSharp
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("libPorygonLang", EntryPoint = "CreateScript", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("libPorygonLang", EntryPoint = "CreateScript", CallingConvention = CallingConvention.Cdecl)]
|
||||||
private static extern IntPtr Create([MarshalAs(UnmanagedType.LPWStr)]string s);
|
private static extern IntPtr Create([MarshalAs(UnmanagedType.LPWStr)]string s, IntPtr options);
|
||||||
[DllImport("libPorygonLang", EntryPoint = "EvaluateScript", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("libPorygonLang", EntryPoint = "EvaluateScript", CallingConvention = CallingConvention.Cdecl)]
|
||||||
private static extern IntPtr Evaluate(IntPtr script);
|
private static extern IntPtr Evaluate(IntPtr script);
|
||||||
[DllImport("libPorygonLang", EntryPoint = "HasVariable", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("libPorygonLang", EntryPoint = "HasVariable", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
@ -123,5 +143,9 @@ namespace PorygonSharp
|
||||||
private static extern IntPtr CallFunction(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key,
|
private static extern IntPtr CallFunction(IntPtr script, [MarshalAs(UnmanagedType.LPWStr)]string key,
|
||||||
IntPtr[] parameters, int parameterCount);
|
IntPtr[] parameters, int parameterCount);
|
||||||
|
|
||||||
|
[DllImport("libPorygonLang", EntryPoint = "CloneScript", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern IntPtr CloneScript(IntPtr script);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
// ReSharper disable PrivateFieldCanBeConvertedToLocalVariable
|
||||||
|
|
||||||
|
namespace PorygonSharp
|
||||||
|
{
|
||||||
|
public abstract class ScriptOptions
|
||||||
|
{
|
||||||
|
private readonly IntPtr _ptr;
|
||||||
|
private delegate void PrintDelegate(string s);
|
||||||
|
private delegate bool ModuleExistsDelegate(IntPtr namePtr, int size);
|
||||||
|
private delegate IntPtr ResolveModuleDelegate(IntPtr namePtr, int size);
|
||||||
|
|
||||||
|
private readonly PrintDelegate _print;
|
||||||
|
private readonly ModuleExistsDelegate _moduleExists;
|
||||||
|
private readonly ResolveModuleDelegate _resolveModule;
|
||||||
|
|
||||||
|
protected ScriptOptions()
|
||||||
|
{
|
||||||
|
_ptr = Create();
|
||||||
|
_print = Print;
|
||||||
|
SetOptionPrintFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_print));
|
||||||
|
_moduleExists = (namePtr, size) =>
|
||||||
|
{
|
||||||
|
var nameArr = new byte[size];
|
||||||
|
for (var i = 0; i < size; i++)
|
||||||
|
nameArr[i] = Marshal.ReadByte(namePtr, i);
|
||||||
|
var name = Encoding.UTF8.GetString(nameArr);
|
||||||
|
return ModuleExists(name);
|
||||||
|
};
|
||||||
|
SetOptionModuleExistsFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_moduleExists));
|
||||||
|
_resolveModule = (namePtr, size) =>
|
||||||
|
{
|
||||||
|
var nameArr = new byte[size];
|
||||||
|
for (var i = 0; i < size; i++)
|
||||||
|
nameArr[i] = Marshal.ReadByte(namePtr, i);
|
||||||
|
var name = Encoding.UTF8.GetString(nameArr);
|
||||||
|
return ResolveModule(name).GetRawPointer();
|
||||||
|
};
|
||||||
|
SetOptionResolveModuleFunc(_ptr, Marshal.GetFunctionPointerForDelegate(_resolveModule));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void Print(string s);
|
||||||
|
protected abstract bool ModuleExists(string s);
|
||||||
|
protected abstract Script ResolveModule(string s);
|
||||||
|
|
||||||
|
internal IntPtr GetRawPointer()
|
||||||
|
{
|
||||||
|
return _ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("libPorygonLang", EntryPoint = "CreateOptions", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern IntPtr Create();
|
||||||
|
|
||||||
|
[DllImport("libPorygonLang", EntryPoint = "SetOptionPrintFunc", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void SetOptionPrintFunc(IntPtr opt, IntPtr func);
|
||||||
|
|
||||||
|
[DllImport("libPorygonLang", EntryPoint = "SetOptionModuleExistsFunc", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void SetOptionModuleExistsFunc(IntPtr opt, IntPtr func);
|
||||||
|
|
||||||
|
[DllImport("libPorygonLang", EntryPoint = "SetOptionResolveModuleFunc", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
private static extern void SetOptionResolveModuleFunc(IntPtr opt, IntPtr func);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,11 +9,13 @@ namespace PorygonSharp.ScriptType
|
||||||
{
|
{
|
||||||
internal static class ScriptType
|
internal static class ScriptType
|
||||||
{
|
{
|
||||||
internal static IntPtr GetScriptType(Type t)
|
internal static IntPtr? GetScriptType(Type t)
|
||||||
{
|
{
|
||||||
if (t.IsEnum)
|
if (t.IsEnum && !t.IsGenericParameter)
|
||||||
{
|
{
|
||||||
|
if (UserDataHandler.IsTypeRegistered(t))
|
||||||
return UserDataHandler.CreateUserDataType(t);
|
return UserDataHandler.CreateUserDataType(t);
|
||||||
|
return CreateNumericScriptType(true, false);
|
||||||
}
|
}
|
||||||
var typeCode = Type.GetTypeCode(t);
|
var typeCode = Type.GetTypeCode(t);
|
||||||
switch (typeCode)
|
switch (typeCode)
|
||||||
|
@ -49,30 +51,44 @@ namespace PorygonSharp.ScriptType
|
||||||
{
|
{
|
||||||
return CreateUserDataListType(t);
|
return CreateUserDataListType(t);
|
||||||
}
|
}
|
||||||
if (typeof(IDictionary<,>).IsAssignableFrom(t))
|
if (typeof(IDictionary).IsAssignableFrom(t))
|
||||||
{
|
{
|
||||||
return CreateUserDataDictionaryType(t);
|
return CreateUserDataDictionaryType(t);
|
||||||
}
|
}
|
||||||
goto default;
|
|
||||||
|
var attr = t.GetCustomAttribute<Attributes.PorygonUserdataAttribute>();
|
||||||
|
if (attr != null)
|
||||||
|
{
|
||||||
|
UserDataHandler.RegisterType(attr.Identifier, t);
|
||||||
|
return UserDataHandler.CreateUserDataType(t);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(t.FullName);
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IntPtr GetFunctionScriptType(MethodInfo info)
|
internal static IntPtr? GetFunctionScriptType(MethodInfo info)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var returnType = GetScriptType(info.ReturnType);
|
var returnType = GetScriptType(info.ReturnType);
|
||||||
|
if (!returnType.HasValue)
|
||||||
|
return null;
|
||||||
var parameters = info.GetParameters();
|
var parameters = info.GetParameters();
|
||||||
var parameterFuncs = new IntPtr[parameters.Length];
|
var parameterFuncs = new IntPtr[parameters.Length];
|
||||||
for (var index = 0; index < parameters.Length; index++)
|
for (var index = 0; index < parameters.Length; index++)
|
||||||
{
|
{
|
||||||
var parameter = parameters[index];
|
var parameter = parameters[index];
|
||||||
parameterFuncs[index] = GetScriptType(parameter.ParameterType);
|
var parameterType = GetScriptType(parameter.ParameterType);
|
||||||
|
if (!parameterType.HasValue)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
parameterFuncs[index] = parameterType.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CreateUserDataFunctionScriptType(returnType, parameterFuncs, parameters.Length);
|
return CreateUserDataFunctionScriptType(returnType.Value, parameterFuncs, parameters.Length);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -80,19 +96,23 @@ namespace PorygonSharp.ScriptType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IntPtr CreateUserDataListType(Type t)
|
private static IntPtr? CreateUserDataListType(Type t)
|
||||||
{
|
{
|
||||||
var keyType = CreateNumericScriptType(true, false);
|
var keyType = CreateNumericScriptType(true, false);
|
||||||
var valType = t.IsArray ? t.GetElementType() : t.GenericTypeArguments[0];
|
var valType = t.IsArray ? t.GetElementType() : t.GenericTypeArguments[0];
|
||||||
var valueType = GetScriptType(valType);
|
var valueType = GetScriptType(valType);
|
||||||
return CreateCollectionType(keyType, valueType);
|
if (valueType.HasValue)
|
||||||
|
return CreateCollectionType(keyType, valueType.Value);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IntPtr CreateUserDataDictionaryType(Type t)
|
private static IntPtr? CreateUserDataDictionaryType(Type t)
|
||||||
{
|
{
|
||||||
var keyType = GetScriptType(t.GenericTypeArguments[0]);
|
var keyType = GetScriptType(t.GenericTypeArguments[0]);
|
||||||
var valueType = GetScriptType(t.GenericTypeArguments[1]);
|
var valueType = GetScriptType(t.GenericTypeArguments[1]);
|
||||||
return CreateCollectionType(keyType, valueType);
|
if (keyType.HasValue && valueType.HasValue)
|
||||||
|
return CreateCollectionType(keyType.Value, valueType.Value);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("libPorygonLang", EntryPoint = "CreateScriptType", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("libPorygonLang", EntryPoint = "CreateScriptType", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
|
|
@ -13,7 +13,9 @@ namespace PorygonSharp
|
||||||
var scriptType = ScriptType.ScriptType.GetScriptType(type);
|
var scriptType = ScriptType.ScriptType.GetScriptType(type);
|
||||||
var hash = name.ScriptHash();
|
var hash = name.ScriptHash();
|
||||||
var value = EvalValueCreator.CreateValue(o);
|
var value = EvalValueCreator.CreateValue(o);
|
||||||
RegisterStaticVariable(hash, scriptType, value.GetPointer());
|
if (!scriptType.HasValue)
|
||||||
|
return;
|
||||||
|
RegisterStaticVariable(hash, scriptType.Value, value.GetPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("libPorygonLang", EntryPoint = "RegisterStaticVariable", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("libPorygonLang", EntryPoint = "RegisterStaticVariable", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
|
|
@ -40,10 +40,13 @@ namespace PorygonSharp.UserData
|
||||||
public static void RegisterType(string name, Type type)
|
public static void RegisterType(string name, Type type)
|
||||||
{
|
{
|
||||||
var hash = name.ScriptHash();
|
var hash = name.ScriptHash();
|
||||||
RegisterUserDataType(hash);
|
lock (UserDataLookup)
|
||||||
|
{
|
||||||
if (UserDataLookup.ContainsKey(type))
|
if (UserDataLookup.ContainsKey(type))
|
||||||
return;
|
return;
|
||||||
|
RegisterUserDataType(hash);
|
||||||
UserDataLookup.Add(type, hash);
|
UserDataLookup.Add(type, hash);
|
||||||
|
}
|
||||||
|
|
||||||
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance |
|
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance |
|
||||||
BindingFlags.FlattenHierarchy | BindingFlags.Static;
|
BindingFlags.FlattenHierarchy | BindingFlags.Static;
|
||||||
|
@ -69,9 +72,9 @@ namespace PorygonSharp.UserData
|
||||||
public static void RegisterEnumType(string name, Type type)
|
public static void RegisterEnumType(string name, Type type)
|
||||||
{
|
{
|
||||||
var hash = name.ScriptHash();
|
var hash = name.ScriptHash();
|
||||||
RegisterUserDataType(hash);
|
|
||||||
if (UserDataLookup.ContainsKey(type))
|
if (UserDataLookup.ContainsKey(type))
|
||||||
return;
|
return;
|
||||||
|
RegisterUserDataType(hash);
|
||||||
UserDataLookup.Add(type, hash);
|
UserDataLookup.Add(type, hash);
|
||||||
var values = Enum.GetValues(type);
|
var values = Enum.GetValues(type);
|
||||||
foreach (var value in values)
|
foreach (var value in values)
|
||||||
|
@ -107,7 +110,9 @@ namespace PorygonSharp.UserData
|
||||||
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
|
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
|
||||||
}
|
}
|
||||||
var scriptType = ScriptType.ScriptType.GetScriptType(field.FieldType);
|
var scriptType = ScriptType.ScriptType.GetScriptType(field.FieldType);
|
||||||
var userDataField = CreateUserDataField(scriptType, Marshal.GetFunctionPointerForDelegate(getter),
|
if (!scriptType.HasValue)
|
||||||
|
return;
|
||||||
|
var userDataField = CreateUserDataField(scriptType.Value, Marshal.GetFunctionPointerForDelegate(getter),
|
||||||
setterPtr);
|
setterPtr);
|
||||||
|
|
||||||
var fieldName = field.Name.ScriptHash();
|
var fieldName = field.Name.ScriptHash();
|
||||||
|
@ -139,7 +144,9 @@ namespace PorygonSharp.UserData
|
||||||
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
|
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
|
||||||
}
|
}
|
||||||
var scriptType = ScriptType.ScriptType.GetScriptType(property.PropertyType);
|
var scriptType = ScriptType.ScriptType.GetScriptType(property.PropertyType);
|
||||||
var userDataField = CreateUserDataField(scriptType, getterPtr, setterPtr);
|
if (!scriptType.HasValue)
|
||||||
|
return;
|
||||||
|
var userDataField = CreateUserDataField(scriptType.Value, getterPtr, setterPtr);
|
||||||
|
|
||||||
var fieldName = property.Name.ScriptHash();
|
var fieldName = property.Name.ScriptHash();
|
||||||
RegisterUserDataField(typeHash, fieldName, userDataField);
|
RegisterUserDataField(typeHash, fieldName, userDataField);
|
||||||
|
@ -172,9 +179,9 @@ namespace PorygonSharp.UserData
|
||||||
});
|
});
|
||||||
var getterPtr = Marshal.GetFunctionPointerForDelegate(getter);
|
var getterPtr = Marshal.GetFunctionPointerForDelegate(getter);
|
||||||
var type = ScriptType.ScriptType.GetFunctionScriptType(method);
|
var type = ScriptType.ScriptType.GetFunctionScriptType(method);
|
||||||
if (type == IntPtr.Zero)
|
if (type == IntPtr.Zero || !type.HasValue)
|
||||||
return;
|
return;
|
||||||
var userDataField = CreateUserDataField(type, getterPtr, IntPtr.Zero);
|
var userDataField = CreateUserDataField(type.Value, getterPtr, IntPtr.Zero);
|
||||||
|
|
||||||
var fieldName = method.Name.ScriptHash();
|
var fieldName = method.Name.ScriptHash();
|
||||||
RegisterUserDataField(typeHash, fieldName, userDataField);
|
RegisterUserDataField(typeHash, fieldName, userDataField);
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue