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)
|
||||
{
|
||||
var type = o.GetType();
|
||||
if (type.IsEnum)
|
||||
if (type.IsEnum && !type.IsGenericParameter)
|
||||
{
|
||||
var typeHash = UserDataHandler.GetTypeId(type);
|
||||
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
||||
|
@ -41,6 +41,8 @@ namespace PorygonSharp.EvalValues
|
|||
case TypeCode.Object:
|
||||
if (typeof(IList).IsAssignableFrom(type))
|
||||
return CreateListEvalValue((IList)o, type);
|
||||
if (!UserDataHandler.IsTypeRegistered(type))
|
||||
return null;
|
||||
var typeHash = UserDataHandler.GetTypeId(type);
|
||||
var handle = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
|
||||
return new EvalValue(CreateUserDataEvalValue(typeHash, GCHandle.ToIntPtr(handle)));
|
||||
|
|
|
@ -10,5 +10,4 @@
|
|||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -43,23 +43,43 @@ namespace PorygonSharp
|
|||
|
||||
private Diagnostics _diagnostics;
|
||||
public Diagnostics Diagnostics => _diagnostics ?? (_diagnostics = new Diagnostics(_internalScript.Diagnostics));
|
||||
public bool HasErrors => Diagnostics.HasErrors();
|
||||
|
||||
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
|
||||
RuntimeHelpers.RunClassConstructor(SetupHandle);
|
||||
|
||||
_internalScriptHandle = Create(s);
|
||||
var optionsPointer = options?.GetRawPointer() ?? IntPtr.Zero;
|
||||
_internalScriptHandle = Create(s, optionsPointer);
|
||||
_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()
|
||||
{
|
||||
Marshal.FreeHGlobal(_internalScriptHandle);
|
||||
}
|
||||
|
||||
internal IntPtr GetRawPointer()
|
||||
{
|
||||
return _internalScriptHandle;
|
||||
}
|
||||
|
||||
public EvalValue Evaluate()
|
||||
{
|
||||
var ptr = Evaluate(_internalScriptHandle);
|
||||
|
@ -108,7 +128,7 @@ namespace PorygonSharp
|
|||
}
|
||||
|
||||
[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)]
|
||||
private static extern IntPtr Evaluate(IntPtr script);
|
||||
[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,
|
||||
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 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 CreateNumericScriptType(true, false);
|
||||
}
|
||||
var typeCode = Type.GetTypeCode(t);
|
||||
switch (typeCode)
|
||||
|
@ -49,30 +51,44 @@ namespace PorygonSharp.ScriptType
|
|||
{
|
||||
return CreateUserDataListType(t);
|
||||
}
|
||||
if (typeof(IDictionary<,>).IsAssignableFrom(t))
|
||||
if (typeof(IDictionary).IsAssignableFrom(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:
|
||||
throw new ArgumentOutOfRangeException(t.FullName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static IntPtr GetFunctionScriptType(MethodInfo info)
|
||||
internal static IntPtr? GetFunctionScriptType(MethodInfo info)
|
||||
{
|
||||
try
|
||||
{
|
||||
var returnType = GetScriptType(info.ReturnType);
|
||||
if (!returnType.HasValue)
|
||||
return null;
|
||||
var parameters = info.GetParameters();
|
||||
var parameterFuncs = new IntPtr[parameters.Length];
|
||||
for (var index = 0; index < parameters.Length; 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
|
||||
{
|
||||
|
@ -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 valType = t.IsArray ? t.GetElementType() : t.GenericTypeArguments[0];
|
||||
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 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)]
|
||||
|
|
|
@ -13,7 +13,9 @@ namespace PorygonSharp
|
|||
var scriptType = ScriptType.ScriptType.GetScriptType(type);
|
||||
var hash = name.ScriptHash();
|
||||
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)]
|
||||
|
|
|
@ -40,10 +40,13 @@ namespace PorygonSharp.UserData
|
|||
public static void RegisterType(string name, Type type)
|
||||
{
|
||||
var hash = name.ScriptHash();
|
||||
RegisterUserDataType(hash);
|
||||
lock (UserDataLookup)
|
||||
{
|
||||
if (UserDataLookup.ContainsKey(type))
|
||||
return;
|
||||
RegisterUserDataType(hash);
|
||||
UserDataLookup.Add(type, hash);
|
||||
}
|
||||
|
||||
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance |
|
||||
BindingFlags.FlattenHierarchy | BindingFlags.Static;
|
||||
|
@ -69,9 +72,9 @@ namespace PorygonSharp.UserData
|
|||
public static void RegisterEnumType(string name, Type type)
|
||||
{
|
||||
var hash = name.ScriptHash();
|
||||
RegisterUserDataType(hash);
|
||||
if (UserDataLookup.ContainsKey(type))
|
||||
return;
|
||||
RegisterUserDataType(hash);
|
||||
UserDataLookup.Add(type, hash);
|
||||
var values = Enum.GetValues(type);
|
||||
foreach (var value in values)
|
||||
|
@ -107,7 +110,9 @@ namespace PorygonSharp.UserData
|
|||
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
|
||||
}
|
||||
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);
|
||||
|
||||
var fieldName = field.Name.ScriptHash();
|
||||
|
@ -139,7 +144,9 @@ namespace PorygonSharp.UserData
|
|||
setterPtr = Marshal.GetFunctionPointerForDelegate(setter);
|
||||
}
|
||||
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();
|
||||
RegisterUserDataField(typeHash, fieldName, userDataField);
|
||||
|
@ -172,9 +179,9 @@ namespace PorygonSharp.UserData
|
|||
});
|
||||
var getterPtr = Marshal.GetFunctionPointerForDelegate(getter);
|
||||
var type = ScriptType.ScriptType.GetFunctionScriptType(method);
|
||||
if (type == IntPtr.Zero)
|
||||
if (type == IntPtr.Zero || !type.HasValue)
|
||||
return;
|
||||
var userDataField = CreateUserDataField(type, getterPtr, IntPtr.Zero);
|
||||
var userDataField = CreateUserDataField(type.Value, getterPtr, IntPtr.Zero);
|
||||
|
||||
var fieldName = method.Name.ScriptHash();
|
||||
RegisterUserDataField(typeHash, fieldName, userDataField);
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue