diff --git a/PorygonSharp/EvalValues/EvalValue.cs b/PorygonSharp/EvalValues/EvalValue.cs index 1ddeb63..c1ee037 100644 --- a/PorygonSharp/EvalValues/EvalValue.cs +++ b/PorygonSharp/EvalValues/EvalValue.cs @@ -64,6 +64,12 @@ namespace PorygonSharp.EvalValues var ptr = EvaluateUserDataObj(Handle); return GCHandle.FromIntPtr(ptr).Target; } + + private object EvaluateUserdataCollection() + { + var listHelper = ListEvalValue.Fetch(Handle); + return listHelper.List; + } public object GetObjectValue() { @@ -74,7 +80,7 @@ namespace PorygonSharp.EvalValues case TypeClass.Nil: return null; case TypeClass.Number: - if (IsNumericValueFloat(Handle) == 1) + if (IsNumericValueFloat()) return EvaluateFloat(); else return EvaluateInteger(); @@ -84,6 +90,8 @@ namespace PorygonSharp.EvalValues return EvaluateString(); case TypeClass.UserData: return EvaluateGenericObject(); + case TypeClass.UserdataCollection: + return EvaluateUserdataCollection(); case TypeClass.Table: var val = new TableEvalValue(Handle); return val.EvaluateNumericalTable(); @@ -97,6 +105,11 @@ namespace PorygonSharp.EvalValues return Handle; } + public bool IsNumericValueFloat() + { + return IsNumericValueFloat(Handle) == 1; + } + [DllImport("PorygonLang", EntryPoint = "GetEvalValueTypeClass", CallingConvention = CallingConvention.Cdecl)] private static extern int GetTypeClass(IntPtr ptr); [DllImport("PorygonLang", EntryPoint = "GetEvalValueType", CallingConvention = CallingConvention.Cdecl)] diff --git a/PorygonSharp/EvalValues/EvalValueCreator.cs b/PorygonSharp/EvalValues/EvalValueCreator.cs index 488f000..becdfc6 100644 --- a/PorygonSharp/EvalValues/EvalValueCreator.cs +++ b/PorygonSharp/EvalValues/EvalValueCreator.cs @@ -64,9 +64,7 @@ namespace PorygonSharp.EvalValues private static EvalValue CreateListEvalValue(IList collection, Type type) { - var helper = new ListEvalValue(collection, type); - var ptr = CreateCollectionValue(IntPtr.Zero, helper.ParentCollectionPtr, helper.GetterPtr, helper.SetterPtr, - helper.GetIteratorPtr, helper.GetLengthPtr); + var ptr = ListEvalValue.Create(collection, type); return new EvalValue(ptr); } @@ -100,7 +98,7 @@ namespace PorygonSharp.EvalValues internal static extern IntPtr CreateFunctionEvalValue(IntPtr func, IntPtr parent); [DllImport("PorygonLang", EntryPoint = "CreateCollectionValue", CallingConvention = CallingConvention.Cdecl)] - private static extern IntPtr CreateCollectionValue(IntPtr type, IntPtr parent, IntPtr getter, IntPtr setter, + internal static extern IntPtr CreateCollectionValue(IntPtr type, IntPtr parent, IntPtr getter, IntPtr setter, IntPtr iterator, IntPtr size); } } \ No newline at end of file diff --git a/PorygonSharp/EvalValues/ListEvalValue.cs b/PorygonSharp/EvalValues/ListEvalValue.cs index 267d3a8..46414b2 100644 --- a/PorygonSharp/EvalValues/ListEvalValue.cs +++ b/PorygonSharp/EvalValues/ListEvalValue.cs @@ -1,12 +1,17 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.Runtime.InteropServices; +using PorygonSharp.Utilities; namespace PorygonSharp.EvalValues { internal class ListEvalValue { - private readonly IList _list; + private static readonly ConcurrentDictionary> _cache + = new ConcurrentDictionary>(); + + public IList List { get; } private readonly Type _valueType; private delegate IntPtr GetterDelegate(IntPtr parent, IntPtr index); @@ -28,9 +33,9 @@ namespace PorygonSharp.EvalValues public readonly IntPtr GetLengthPtr; - public ListEvalValue(IList list, Type type) + private ListEvalValue(IList list, Type type) { - _list = list; + List = list; _valueType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0]; if (_valueType == null) throw new ArgumentNullException(); @@ -46,29 +51,51 @@ namespace PorygonSharp.EvalValues SetterPtr = Marshal.GetFunctionPointerForDelegate(_setter); GetIteratorPtr = Marshal.GetFunctionPointerForDelegate(_getIterator); GetLengthPtr = Marshal.GetFunctionPointerForDelegate(_getLength); + + } + + public static IntPtr Create(IList list, Type type) + { + var v = new ListEvalValue(list, type); + var ptr = EvalValueCreator.CreateCollectionValue(IntPtr.Zero, v.ParentCollectionPtr, v.GetterPtr, + v.SetterPtr, v.GetIteratorPtr, v.GetLengthPtr); + _cache.TryAdd(ptr, new WeakReference(v)); + return ptr; + } + + internal static ListEvalValue Fetch(IntPtr ptr) + { + if (_cache.TryGetValue(ptr, out var r)) + { + if (r.TryGetTarget(out var v)) + { + return v; + } + } + throw new Exception("Can't get list eval value."); } private IntPtr Getter(IntPtr parent, IntPtr index) { var val = new EvalValue(index).EvaluateInteger(); - return EvalValueCreator.CreateValue(_list[(int) val - 1]).GetPointer(); + return EvalValueCreator.CreateValue(List[(int) val - 1]).GetPointer(); } private void Setter(IntPtr parent, IntPtr index, IntPtr value) { var key = new EvalValue(index).EvaluateInteger(); - var val = new EvalValue(value).GetObjectValue(); - _list[(int) key - 1] = Convert.ChangeType(val, _valueType); + var val = new EvalValue(value); + List[(int) key - 1] = Caster.Cast(val, _valueType); } private IntPtr GetIterator(IntPtr parent) { - return ListIterator.CreateListIterator(_list); + return ListIterator.CreateListIterator(List); } private int GetLength(IntPtr parent) { - return _list.Count; + return List.Count; } } } \ No newline at end of file diff --git a/PorygonSharp/TypeClass.cs b/PorygonSharp/TypeClass.cs index c4da3df..4254e14 100644 --- a/PorygonSharp/TypeClass.cs +++ b/PorygonSharp/TypeClass.cs @@ -9,6 +9,7 @@ namespace PorygonSharp String, Function, UserData, + UserdataCollection, Table, Any } diff --git a/PorygonSharp/libPorygonLang.so b/PorygonSharp/libPorygonLang.so index d53d841..028ab9a 100755 Binary files a/PorygonSharp/libPorygonLang.so and b/PorygonSharp/libPorygonLang.so differ