Fixes for enums and dictionaries

This commit is contained in:
Deukhoofd 2019-09-19 15:44:39 +02:00
parent 1c181442e8
commit 5637e82dbe
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
5 changed files with 106 additions and 10 deletions

View File

@ -0,0 +1,72 @@
using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace PorygonSharp.EvalValues
{
public class DictionaryEvalValue
{
private readonly IDictionary _dictionary;
private readonly Type _keyType;
private readonly Type _valueType;
private delegate IntPtr GetterDelegate(IntPtr parent, IntPtr index);
private delegate void SetterDelegate(IntPtr parent, IntPtr index, IntPtr value);
private delegate IntPtr GetIteratorDelegate(IntPtr parent);
private delegate int GetLengthDelegate(IntPtr parent);
// ReSharper disable PrivateFieldCanBeConvertedToLocalVariable
private readonly GetterDelegate _getter;
private readonly SetterDelegate _setter;
private readonly GetIteratorDelegate _getIterator;
private readonly GetLengthDelegate _getLength;
// ReSharper restore PrivateFieldCanBeConvertedToLocalVariable
public readonly IntPtr GetterPtr;
public readonly IntPtr SetterPtr;
public readonly IntPtr GetIteratorPtr;
public readonly IntPtr GetLengthPtr;
public DictionaryEvalValue(IDictionary dictionary, Type t)
{
_dictionary = dictionary;
var genericTypes = t.GetGenericArguments();
_keyType = genericTypes[0];
_valueType = genericTypes[1];
_getter = Getter;
_setter = Setter;
_getIterator = GetIterator;
_getLength = GetLength;
GetterPtr = Marshal.GetFunctionPointerForDelegate(_getter);
SetterPtr = Marshal.GetFunctionPointerForDelegate(_setter);
GetIteratorPtr = Marshal.GetFunctionPointerForDelegate(_getIterator);
GetLengthPtr = Marshal.GetFunctionPointerForDelegate(_getLength);
}
private IntPtr Getter(IntPtr parent, IntPtr index)
{
var val = new EvalValue(index).GetObjectValue();
return EvalValueCreator.CreateValue(_dictionary[val]).GetPointer();
}
private void Setter(IntPtr parent, IntPtr index, IntPtr value)
{
var key = new EvalValue(index).GetObjectValue();
var val = new EvalValue(value).GetObjectValue();
_dictionary[key] = Convert.ChangeType(val, _valueType);
}
private IntPtr GetIterator(IntPtr parent)
{
throw new NotImplementedException();
}
private int GetLength(IntPtr parent)
{
return _dictionary.Count;
}
}
}

View File

@ -14,9 +14,6 @@ namespace PorygonSharp.EvalValues
var type = o.GetType(); var type = o.GetType();
if (type.IsEnum && !type.IsGenericParameter) if (type.IsEnum && !type.IsGenericParameter)
{ {
var typeHash = UserDataHandler.GetTypeId(type);
var ptr = ObjectEvalValueHandler.GetObjectPtr(o);
return new EvalValue(CreateUserDataEvalValue(typeHash, ptr));
} }
var typeCode = Type.GetTypeCode(type); var typeCode = Type.GetTypeCode(type);
switch (typeCode) switch (typeCode)
@ -42,6 +39,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 (typeof(IDictionary).IsAssignableFrom(type))
return CreateDictionaryEvalValue((IDictionary) o, type);
if (typeof(Delegate).IsAssignableFrom(type)) if (typeof(Delegate).IsAssignableFrom(type))
{ {
return CreateDelegateEvalValue((Delegate) o); return CreateDelegateEvalValue((Delegate) o);
@ -71,6 +70,14 @@ namespace PorygonSharp.EvalValues
return new EvalValue(ptr); return new EvalValue(ptr);
} }
private static EvalValue CreateDictionaryEvalValue(IDictionary dictionary, Type t)
{
var helper = new DictionaryEvalValue(dictionary, t);
var ptr = CreateCollectionValue(IntPtr.Zero, IntPtr.Zero, helper.GetterPtr, helper.SetterPtr,
helper.GetIteratorPtr, helper.GetLengthPtr);
return new EvalValue(ptr);
}
private static EvalValue CreateDelegateEvalValue(Delegate del) private static EvalValue CreateDelegateEvalValue(Delegate del)
{ {
var val = new DelegateEvalValue(del); var val = new DelegateEvalValue(del);
@ -88,7 +95,7 @@ namespace PorygonSharp.EvalValues
[DllImport("PorygonLang", EntryPoint = "CreateStringEvalValue",CallingConvention = CallingConvention.Cdecl)] [DllImport("PorygonLang", EntryPoint = "CreateStringEvalValue",CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateStringEvalValue([MarshalAs(UnmanagedType.LPWStr)]string s); private static extern IntPtr CreateStringEvalValue([MarshalAs(UnmanagedType.LPWStr)]string s);
[DllImport("PorygonLang", EntryPoint = "CreateUserDataEvalValue",CallingConvention = CallingConvention.Cdecl)] [DllImport("PorygonLang", EntryPoint = "CreateUserDataEvalValue",CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr CreateUserDataEvalValue(uint typeHash, IntPtr obj); internal static extern IntPtr CreateUserDataEvalValue(uint typeHash, IntPtr obj);
[DllImport("PorygonLang", EntryPoint = "CreateFunctionEvalValue",CallingConvention = CallingConvention.Cdecl)] [DllImport("PorygonLang", EntryPoint = "CreateFunctionEvalValue",CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr CreateFunctionEvalValue(IntPtr func, IntPtr parent); internal static extern IntPtr CreateFunctionEvalValue(IntPtr func, IntPtr parent);

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using PorygonSharp.EvalValues; using PorygonSharp.EvalValues;
using PorygonSharp.UserData;
using PorygonSharp.Utilities; using PorygonSharp.Utilities;
namespace PorygonSharp namespace PorygonSharp
@ -20,6 +21,25 @@ namespace PorygonSharp
_variables.Add(o); _variables.Add(o);
RegisterStaticVariable(hash, scriptType.Value, value.GetPointer()); RegisterStaticVariable(hash, scriptType.Value, value.GetPointer());
} }
public static void RegisterStaticEnum(string name, Type type)
{
UserDataHandler.RegisterEnumType(name, type);
var typeHash = UserDataHandler.GetTypeId(type);
var scriptType = ScriptType.ScriptTypeHandler.GetScriptType(type);
if (!scriptType.HasValue)
return;
var ptr = ObjectEvalValueHandler.GetObjectPtr(Activator.CreateInstance(type));
var val = new EvalValue(EvalValueCreator.CreateUserDataEvalValue(typeHash, ptr));
StaticScope.RegisterStaticVariable(name, scriptType.Value, val);
}
public static void RegisterStaticVariable(string name, IntPtr type, EvalValue val)
{
var hash = name.ScriptHash();
RegisterStaticVariable(hash, type, val.GetPointer());
}
[DllImport("PorygonLang", EntryPoint = "RegisterStaticVariable", CallingConvention = CallingConvention.Cdecl)] [DllImport("PorygonLang", EntryPoint = "RegisterStaticVariable", CallingConvention = CallingConvention.Cdecl)]
private static extern void RegisterStaticVariable(uint hashId, IntPtr scriptType, IntPtr value); private static extern void RegisterStaticVariable(uint hashId, IntPtr scriptType, IntPtr value);

View File

@ -27,8 +27,7 @@ namespace PorygonSharp.UserData
var enumAttr = type.GetCustomAttribute<PorygonEnumAttribute>(); var enumAttr = type.GetCustomAttribute<PorygonEnumAttribute>();
if (enumAttr != null) if (enumAttr != null)
{ {
RegisterEnumType(enumAttr.Name, type); StaticScope.RegisterStaticEnum(enumAttr.Name, type);
StaticScope.RegisterStaticVariable(enumAttr.Name, Activator.CreateInstance(type));
} }
} }
} }

View File

@ -15,8 +15,7 @@ namespace PorygonSharpTests
[Test] [Test]
public void AbleToAccessStaticEnumVariable() public void AbleToAccessStaticEnumVariable()
{ {
UserDataHandler.RegisterEnumType("testEnum", typeof(testEnum)); StaticScope.RegisterStaticEnum("testEnum", typeof(testEnum));
StaticScope.RegisterStaticVariable("testEnum", testEnum.One);
using (var script = new Script(@" using (var script = new Script(@"
return type(testEnum) return type(testEnum)
")) "))
@ -34,8 +33,7 @@ namespace PorygonSharpTests
[Test] [Test]
public void AbleToUseStaticEnumVariable() public void AbleToUseStaticEnumVariable()
{ {
UserDataHandler.RegisterEnumType("testEnum", typeof(testEnum)); StaticScope.RegisterStaticEnum("testEnum", typeof(testEnum));
StaticScope.RegisterStaticVariable("testEnum", testEnum.One);
using (var script = new Script(@" using (var script = new Script(@"
return testEnum.Three + 2 return testEnum.Three + 2
")) "))