Large amount of fixes and improvements
This commit is contained in:
		| @@ -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); | ||||||
|  |  | ||||||
|  |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										67
									
								
								PorygonSharp/ScriptOptions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								PorygonSharp/ScriptOptions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||||
|             { |             { | ||||||
|                 return UserDataHandler.CreateUserDataType(t); |                 if (UserDataHandler.IsTypeRegistered(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)) |             { | ||||||
|                 return; |                 if (UserDataLookup.ContainsKey(type)) | ||||||
|             UserDataLookup.Add(type, hash); |                     return; | ||||||
|  |                 RegisterUserDataType(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.
										
									
								
							
		Reference in New Issue
	
	Block a user