瀏覽代碼

Method interop ok.

Xanathar 11 年之前
父節點
當前提交
d7b4a47b6e

+ 102 - 9
src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataMethodsTests.cs

@@ -2,7 +2,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-using MoonSharp.Interpreter.Interop;
 using NUnit.Framework;
 
 namespace MoonSharp.Interpreter.Tests.EndToEnd
@@ -12,7 +11,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 	{
 		public class SomeClass : IComparable
 		{
-			public StringBuilder Concat(int p1, string p2, IComparable p3, bool p4, List<object> p5, IEnumerable<object> p6, 
+			public static StringBuilder ConcatS(int p1, string p2, IComparable p3, bool p4, List<object> p5, IEnumerable<object> p6, 
 				StringBuilder p7, Dictionary<object, object> p8, SomeClass p9, int p10 = 1994)
 			{
 				p7.Append(p1);
@@ -36,6 +35,12 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 				return p7;
 			}
 
+			public StringBuilder ConcatI(int p1, string p2, IComparable p3, bool p4, List<object> p5, IEnumerable<object> p6,
+				StringBuilder p7, Dictionary<object, object> p8, SomeClass p9, int p10 = 1912)
+			{
+				return ConcatS(p1, p2, p3, p4, p5, p6, p7, p8, this, p10);
+			}
+
 			public override string ToString()
 			{
 				return "!SOMECLASS!";
@@ -49,36 +54,124 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 		}
 
 
-		public void Test_ConcatMethod(UserDataOptimizationMode opt)
+		public void Test_ConcatMethodStatic(UserDataAccessMode opt)
 		{
 			string script = @"    
 				t = { 'asd', 'qwe', 'zxc', ['x'] = 'X', ['y'] = 'Y' };
-				x = myobj.Concat(1, 'ciao', myobj, true, t, t, 'eheh', t, myobj);
+				x = static.ConcatS(1, 'ciao', myobj, true, t, t, 'eheh', t, myobj);
 				return x;";
 
 			Script S = new Script();
 
 			SomeClass obj = new SomeClass();
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
+			S.Globals.Set("static", UserData.CreateStatic<SomeClass>());
+			S.Globals.Set("myobj", UserData.Create(obj));
 
 			DynValue res = S.DoString(script);
 
-			// expected:
-			// "eheh1ciao!SOMECLASS!True|asdqwezxc|asdqwezxc|123xy|XYasdqwezxc|!SOMECLASS!1994";
+			Assert.AreEqual(DataType.String, res.Type);
+			Assert.AreEqual("eheh1ciao!SOMECLASS!True|asdqwezxc|asdqwezxc|123xy|asdqweXYzxc|!SOMECLASS!1994", res.String);
+		}
+		public void Test_ConcatMethod(UserDataAccessMode opt)
+		{
+			string script = @"    
+				t = { 'asd', 'qwe', 'zxc', ['x'] = 'X', ['y'] = 'Y' };
+				x = myobj.ConcatI(1, 'ciao', myobj, true, t, t, 'eheh', t, myobj);
+				return x;";
+
+			Script S = new Script();
+
+			SomeClass obj = new SomeClass();
+
+			UserData.RegisterType<SomeClass>(opt);
 
+			S.Globals.Set("myobj", UserData.Create(obj));
+
+			DynValue res = S.DoString(script);
+
+			Assert.AreEqual(DataType.String, res.Type);
+			Assert.AreEqual("eheh1ciao!SOMECLASS!True|asdqwezxc|asdqwezxc|123xy|asdqweXYzxc|!SOMECLASS!1912", res.String);
+		}
+
+		public void Test_ConcatMethodStaticSimplifiedSyntax(UserDataAccessMode opt)
+		{
+			string script = @"    
+				t = { 'asd', 'qwe', 'zxc', ['x'] = 'X', ['y'] = 'Y' };
+				x = static.ConcatS(1, 'ciao', myobj, true, t, t, 'eheh', t, myobj);
+				return x;";
+
+			Script S = new Script();
+
+			SomeClass obj = new SomeClass();
+
+			UserData.RegisterType<SomeClass>(opt);
+
+			S.Globals["static"] = typeof(SomeClass);
+			S.Globals["myobj"] = obj;
+
+			DynValue res = S.DoString(script);
 
 			Assert.AreEqual(DataType.String, res.Type);
 			Assert.AreEqual("eheh1ciao!SOMECLASS!True|asdqwezxc|asdqwezxc|123xy|asdqweXYzxc|!SOMECLASS!1994", res.String);
 		}
 
+
 		[Test]
 		public void Interpo_ConcatMethod_None()
 		{
-			Test_ConcatMethod(UserDataOptimizationMode.None);
+			Test_ConcatMethod(UserDataAccessMode.Reflection);
+		}
+
+		[Test]
+		public void Interpo_ConcatMethod_Lazy()
+		{
+			Test_ConcatMethod(UserDataAccessMode.LazyOptimized);
+		}
+
+		[Test]
+		public void Interpo_ConcatMethod_Precomputed()
+		{
+			Test_ConcatMethod(UserDataAccessMode.Preoptimized);
+		}
+
+		[Test]
+		public void Interpo_ConcatMethodStatic_None()
+		{
+			Test_ConcatMethodStatic(UserDataAccessMode.Reflection);
+		}
+
+		[Test]
+		public void Interpo_ConcatMethodStatic_Lazy()
+		{
+			Test_ConcatMethodStatic(UserDataAccessMode.LazyOptimized);
 		}
 
+		[Test]
+		public void Interpo_ConcatMethodStatic_Precomputed()
+		{
+			Test_ConcatMethodStatic(UserDataAccessMode.Preoptimized);
+		}
+
+
+		[Test]
+		public void Interpo_ConcatMethodStaticSimplifiedSyntax_None()
+		{
+			Test_ConcatMethodStaticSimplifiedSyntax(UserDataAccessMode.Reflection);
+		}
+
+		[Test]
+		public void Interpo_ConcatMethodStaticSimplifiedSyntax_Lazy()
+		{
+			Test_ConcatMethodStaticSimplifiedSyntax(UserDataAccessMode.LazyOptimized);
+		}
+
+		[Test]
+		public void Interpo_ConcatMethodStaticSimplifiedSyntax_Precomputed()
+		{
+			Test_ConcatMethodStaticSimplifiedSyntax(UserDataAccessMode.Preoptimized);
+		}
 	}
 }

+ 59 - 60
src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataPropertiesTests.cs

@@ -2,7 +2,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
-using MoonSharp.Interpreter.Interop;
 using NUnit.Framework;
 
 namespace MoonSharp.Interpreter.Tests.EndToEnd
@@ -27,7 +26,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			}
 		}
 
-		public void Test_IntPropertyGetter(UserDataOptimizationMode opt)
+		public void Test_IntPropertyGetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				x = myobj.IntProp;
@@ -37,9 +36,9 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			SomeClass obj = new SomeClass() {  IntProp = 321 };
 			
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
+			S.Globals.Set("myobj", UserData.Create(obj));
 
 			DynValue res = S.DoString(script);
 
@@ -47,7 +46,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual(321, res.Number);
 		}
 
-		public void Test_NIntPropertyGetter(UserDataOptimizationMode opt)
+		public void Test_NIntPropertyGetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				x = myobj1.NIntProp;
@@ -59,10 +58,10 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			SomeClass obj1 = new SomeClass() { NIntProp = 321 };
 			SomeClass obj2 = new SomeClass() { NIntProp = null };
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
-			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
+			S.Globals.Set("myobj1", UserData.Create(obj1));
+			S.Globals.Set("myobj2", UserData.Create(obj2));
 
 			DynValue res = S.DoString(script);
 
@@ -72,7 +71,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual(DataType.Nil, res.Tuple[1].Type);
 		}
 
-		public void Test_ObjPropertyGetter(UserDataOptimizationMode opt)
+		public void Test_ObjPropertyGetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				x = myobj1.ObjProp;
@@ -85,10 +84,10 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			SomeClass obj1 = new SomeClass() { ObjProp="ciao" };
 			SomeClass obj2 = new SomeClass() { ObjProp = obj1 };
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
-			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
+			S.Globals.Set("myobj1", UserData.Create(obj1));
+			S.Globals.Set("myobj2", UserData.Create(obj2));
 
 			DynValue res = S.DoString(script);
 
@@ -101,7 +100,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual(obj1, res.Tuple[1].UserData.Object);
 		}
 
-		public void Test_IntPropertySetter(UserDataOptimizationMode opt)
+		public void Test_IntPropertySetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				myobj.IntProp = 19;";
@@ -110,9 +109,9 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			SomeClass obj = new SomeClass() { IntProp = 321 };
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
+			S.Globals.Set("myobj", UserData.Create(obj));
 
 			Assert.AreEqual(321, obj.IntProp);
 
@@ -121,7 +120,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual(19, obj.IntProp);
 		}
 
-		public void Test_NIntPropertySetter(UserDataOptimizationMode opt)
+		public void Test_NIntPropertySetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				myobj1.NIntProp = nil;
@@ -132,10 +131,10 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			SomeClass obj1 = new SomeClass() { NIntProp = 321 };
 			SomeClass obj2 = new SomeClass() { NIntProp = null };
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
-			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
+			S.Globals.Set("myobj1", UserData.Create(obj1));
+			S.Globals.Set("myobj2", UserData.Create(obj2));
 
 			Assert.AreEqual(321, obj1.NIntProp);
 			Assert.AreEqual(null, obj2.NIntProp);
@@ -146,7 +145,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual(19, obj2.NIntProp);
 		}
 
-		public void Test_ObjPropertySetter(UserDataOptimizationMode opt)
+		public void Test_ObjPropertySetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				myobj1.ObjProp = myobj2;
@@ -157,10 +156,10 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			SomeClass obj1 = new SomeClass() { ObjProp = "ciao" };
 			SomeClass obj2 = new SomeClass() { ObjProp = obj1 };
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
-			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
+			S.Globals.Set("myobj1", UserData.Create(obj1));
+			S.Globals.Set("myobj2", UserData.Create(obj2));
 
 			Assert.AreEqual("ciao", obj1.ObjProp);
 			Assert.AreEqual(obj1, obj2.ObjProp);
@@ -171,7 +170,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual("hello", obj2.ObjProp);
 		}
 
-		public void Test_InvalidPropertySetter(UserDataOptimizationMode opt)
+		public void Test_InvalidPropertySetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				myobj.IntProp = '19';";
@@ -180,9 +179,9 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			SomeClass obj = new SomeClass() { IntProp = 321 };
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
+			S.Globals.Set("myobj", UserData.Create(obj));
 
 			Assert.AreEqual(321, obj.IntProp);
 
@@ -191,7 +190,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual(19, obj.IntProp);
 		}
 
-		public void Test_StaticPropertyAccess(UserDataOptimizationMode opt)
+		public void Test_StaticPropertyAccess(UserDataAccessMode opt)
 		{
 			string script = @"    
 				static.StaticProp = 'asdasd' .. static.StaticProp;";
@@ -200,9 +199,9 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			SomeClass.StaticProp = "qweqwe";
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("static", S.UserDataRepository.CreateStaticUserData<SomeClass>());
+			S.Globals.Set("static", UserData.CreateStatic<SomeClass>());
 
 			Assert.AreEqual("qweqwe", SomeClass.StaticProp);
 
@@ -211,7 +210,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Assert.AreEqual("asdasdqweqwe", SomeClass.StaticProp);
 		}
 
-		public void Test_IteratorPropertyGetter(UserDataOptimizationMode opt)
+		public void Test_IteratorPropertyGetter(UserDataAccessMode opt)
 		{
 			string script = @"    
 				x = 0;
@@ -225,9 +224,9 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			SomeClass obj = new SomeClass();
 
-			S.UserDataRepository.RegisterType<SomeClass>(opt);
+			UserData.RegisterType<SomeClass>(opt);
 
-			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
+			S.Globals.Set("myobj", UserData.Create(obj));
 
 			DynValue res = S.DoString(script);
 
@@ -238,109 +237,109 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 		[Test]
 		public void Interop_IntPropertyGetter_None()
 		{
-			Test_IntPropertyGetter(UserDataOptimizationMode.None);
+			Test_IntPropertyGetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_IntPropertyGetter_Lazy()
 		{
-			Test_IntPropertyGetter(UserDataOptimizationMode.Lazy);
+			Test_IntPropertyGetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_IntPropertyGetter_Precomputed()
 		{
-			Test_IntPropertyGetter(UserDataOptimizationMode.Precomputed);
+			Test_IntPropertyGetter(UserDataAccessMode.Preoptimized);
 		}
 
 		[Test]
 		public void Interop_NIntPropertyGetter_None()
 		{
-			Test_NIntPropertyGetter(UserDataOptimizationMode.None);
+			Test_NIntPropertyGetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_NIntPropertyGetter_Lazy()
 		{
-			Test_NIntPropertyGetter(UserDataOptimizationMode.Lazy);
+			Test_NIntPropertyGetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_NIntPropertyGetter_Precomputed()
 		{
-			Test_NIntPropertyGetter(UserDataOptimizationMode.Precomputed);
+			Test_NIntPropertyGetter(UserDataAccessMode.Preoptimized);
 		}
 
 		[Test]
 		public void Interop_ObjPropertyGetter_None()
 		{
-			Test_ObjPropertyGetter(UserDataOptimizationMode.None);
+			Test_ObjPropertyGetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_ObjPropertyGetter_Lazy()
 		{
-			Test_ObjPropertyGetter(UserDataOptimizationMode.Lazy);
+			Test_ObjPropertyGetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_ObjPropertyGetter_Precomputed()
 		{
-			Test_ObjPropertyGetter(UserDataOptimizationMode.Precomputed);
+			Test_ObjPropertyGetter(UserDataAccessMode.Preoptimized);
 		}
 
 		[Test]
 		public void Interop_IntPropertySetter_None()
 		{
-			Test_IntPropertySetter(UserDataOptimizationMode.None);
+			Test_IntPropertySetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_IntPropertySetter_Lazy()
 		{
-			Test_IntPropertySetter(UserDataOptimizationMode.Lazy);
+			Test_IntPropertySetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_IntPropertySetter_Precomputed()
 		{
-			Test_IntPropertySetter(UserDataOptimizationMode.Precomputed);
+			Test_IntPropertySetter(UserDataAccessMode.Preoptimized);
 		}
 
 		[Test]
 		public void Interop_NIntPropertySetter_None()
 		{
-			Test_NIntPropertySetter(UserDataOptimizationMode.None);
+			Test_NIntPropertySetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_NIntPropertySetter_Lazy()
 		{
-			Test_NIntPropertySetter(UserDataOptimizationMode.Lazy);
+			Test_NIntPropertySetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_NIntPropertySetter_Precomputed()
 		{
-			Test_NIntPropertySetter(UserDataOptimizationMode.Precomputed);
+			Test_NIntPropertySetter(UserDataAccessMode.Preoptimized);
 		}
 
 		[Test]
 		public void Interop_ObjPropertySetter_None()
 		{
-			Test_ObjPropertySetter(UserDataOptimizationMode.None);
+			Test_ObjPropertySetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_ObjPropertySetter_Lazy()
 		{
-			Test_ObjPropertySetter(UserDataOptimizationMode.Lazy);
+			Test_ObjPropertySetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_ObjPropertySetter_Precomputed()
 		{
-			Test_ObjPropertySetter(UserDataOptimizationMode.Precomputed);
+			Test_ObjPropertySetter(UserDataAccessMode.Preoptimized);
 		}
 
 
@@ -348,58 +347,58 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 		[ExpectedException(typeof(ScriptRuntimeException))]
 		public void Interop_InvalidPropertySetter_None()
 		{
-			Test_InvalidPropertySetter(UserDataOptimizationMode.None);
+			Test_InvalidPropertySetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		[ExpectedException(typeof(ScriptRuntimeException))]
 		public void Interop_InvalidPropertySetter_Lazy()
 		{
-			Test_InvalidPropertySetter(UserDataOptimizationMode.Lazy);
+			Test_InvalidPropertySetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		[ExpectedException(typeof(ScriptRuntimeException))]
 		public void Interop_InvalidPropertySetter_Precomputed()
 		{
-			Test_InvalidPropertySetter(UserDataOptimizationMode.Precomputed);
+			Test_InvalidPropertySetter(UserDataAccessMode.Preoptimized);
 		}
 
 
 		[Test]
 		public void Interop_StaticPropertyAccess_None()
 		{
-			Test_StaticPropertyAccess(UserDataOptimizationMode.None);
+			Test_StaticPropertyAccess(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_StaticPropertyAccess_Lazy()
 		{
-			Test_StaticPropertyAccess(UserDataOptimizationMode.Lazy);
+			Test_StaticPropertyAccess(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_StaticPropertyAccess_Precomputed()
 		{
-			Test_StaticPropertyAccess(UserDataOptimizationMode.Precomputed);
+			Test_StaticPropertyAccess(UserDataAccessMode.Preoptimized);
 		}
 
 		[Test]
 		public void Interop_IteratorPropertyGetter_None()
 		{
-			Test_IteratorPropertyGetter(UserDataOptimizationMode.None);
+			Test_IteratorPropertyGetter(UserDataAccessMode.Reflection);
 		}
 
 		[Test]
 		public void Interop_IteratorPropertyGetter_Lazy()
 		{
-			Test_IteratorPropertyGetter(UserDataOptimizationMode.Lazy);
+			Test_IteratorPropertyGetter(UserDataAccessMode.LazyOptimized);
 		}
 
 		[Test]
 		public void Interop_IteratorPropertyGetter_Precomputed()
 		{
-			Test_IteratorPropertyGetter(UserDataOptimizationMode.Precomputed);
+			Test_IteratorPropertyGetter(UserDataAccessMode.Preoptimized);
 		}
 
 		[Test]
@@ -412,7 +411,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			SomeClass obj = new SomeClass() { IntProp = 321 };
 
-			S.UserDataRepository.RegisterType<SomeClass>();
+			UserData.RegisterType<SomeClass>();
 
 			S.Globals["myobj"] = obj;
 

+ 32 - 4
src/MoonSharp.Interpreter/DataTypes/Table.cs

@@ -5,6 +5,7 @@ using System.Linq;
 using System.Text;
 using MoonSharp.Interpreter.DataStructs;
 using MoonSharp.Interpreter.DataTypes;
+using MoonSharp.Interpreter.Execution;
 
 namespace MoonSharp.Interpreter
 {
@@ -291,14 +292,41 @@ namespace MoonSharp.Interpreter
 
 
 
-		public IEnumerable<KeyValuePair<DynValue, DynValue>> EnumerateKeyValuePairs()
+		/// <summary>
+		/// Enumerates the key value pairs.
+		/// </summary>
+		/// <returns></returns>
+		public IEnumerable<KeyValuePair<DynValue, DynValue>> Pairs
 		{
-			return m_Values.Select(n => new KeyValuePair<DynValue, DynValue>(n.Key, n.Value));
+			get
+			{
+				return m_Values.Select(n => new KeyValuePair<DynValue, DynValue>(n.Key, n.Value));
+			}
 		}
-		
-
 
+		/// <summary>
+		/// Enumerates the keys.
+		/// </summary>
+		/// <returns></returns>
+		public IEnumerable<DynValue> Keys
+		{
+			get
+			{
+				return m_Values.Select(n => n.Key);
+			}
+		}
 
+		/// <summary>
+		/// Enumerates the values
+		/// </summary>
+		/// <returns></returns>
+		public IEnumerable<DynValue> Values
+		{
+			get
+			{
+				return m_Values.Select(n => n.Value);
+			}
+		}
 
 
 

+ 143 - 1
src/MoonSharp.Interpreter/DataTypes/UserData.cs

@@ -2,14 +2,156 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using System.Threading;
 using MoonSharp.Interpreter.Interop;
 
 namespace MoonSharp.Interpreter
 {
 	public class UserData
 	{
+		private UserData()
+		{ 
+			// This type can only be instantiated using one of the Create methods
+		}
+
 		public object Object { get; set; }
+		internal UserDataDescriptor Descriptor { get; set; }
+
+		private static ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
+		private static Dictionary<Type, UserDataDescriptor> s_Registry = new Dictionary<Type, UserDataDescriptor>();
+		private static UserDataAccessMode m_DefaultAccessMode;
+
+		static UserData()
+		{
+			RegisterType<EnumerableWrapper>(UserDataAccessMode.HideMembers);
+			m_DefaultAccessMode = UserDataAccessMode.LazyOptimized;
+		}
+
+		public static void RegisterType<T>(UserDataAccessMode accessMode = UserDataAccessMode.Default)
+		{
+			RegisterType_Impl(typeof(T), accessMode);
+		}
+
+		public static void RegisterType(Type type, UserDataAccessMode accessMode = UserDataAccessMode.Default)
+		{
+			RegisterType_Impl(type, accessMode);
+		}
+
+		public static DynValue Create(object o)
+		{
+			var descr = GetDescriptorForObject(o);
+			if (descr == null) return null;
+
+			return DynValue.NewUserData(new UserData()
+				{
+					Descriptor = descr,
+					Object = o
+				});
+		}
+
+		public static DynValue CreateStatic(Type t)
+		{
+			var descr = GetDescriptorForType(t, false);
+			if (descr == null) return null;
+
+			return DynValue.NewUserData(new UserData()
+			{
+				Descriptor = descr,
+				Object = null
+			});
+		}
+
+		public static DynValue CreateStatic<T>()
+		{
+			return CreateStatic(typeof(T));
+		}
+
+		public static UserDataAccessMode DefaultAccessMode
+		{
+			get { return m_DefaultAccessMode; }
+			set
+			{
+				if (value == UserDataAccessMode.Default)
+					throw new ArgumentException("DefaultAccessMode");
+
+				m_DefaultAccessMode = value;
+			}
+		}
+
+
+
+		private static void RegisterType_Impl(Type type, UserDataAccessMode accessMode = UserDataAccessMode.Default)
+		{
+			if (accessMode == UserDataAccessMode.Default)
+			{
+				MoonSharpUserDataAttribute attr = type.GetCustomAttributes(true).OfType<MoonSharpUserDataAttribute>()
+					.SingleOrDefault();
+
+				if (attr != null)
+					accessMode = attr.AccessMode;
+			}
+
+
+			if (accessMode == UserDataAccessMode.Default)
+				accessMode = m_DefaultAccessMode;
+
+			m_Lock.EnterWriteLock();
+
+			try
+			{
+				if (!s_Registry.ContainsKey(type))
+				{
+					UserDataDescriptor udd = new UserDataDescriptor(type, accessMode);
+					s_Registry.Add(udd.Type, udd);
+				}
+			}
+			finally
+			{
+				m_Lock.ExitWriteLock();
+			}
+		}
+
+		private static UserDataDescriptor GetDescriptorForType<T>(bool deepSearch = true)
+		{
+			return GetDescriptorForType(typeof(T), deepSearch);
+		}
+
+		private static UserDataDescriptor GetDescriptorForType(Type type, bool deepSearch = true)
+		{
+			m_Lock.EnterReadLock();
+
+			try
+			{
+				if (!deepSearch)
+					return s_Registry.ContainsKey(type) ? s_Registry[type] : null;
+
+				for (Type t = type; t != typeof(object); t = t.BaseType)
+				{
+					if (s_Registry.ContainsKey(t))
+						return s_Registry[t];
+				}
+
+				foreach (Type t in type.GetInterfaces())
+				{
+					if (s_Registry.ContainsKey(t))
+						return s_Registry[t];
+				}
+
+				if (s_Registry.ContainsKey(typeof(object)))
+					return s_Registry[type];
+			}
+			finally
+			{
+				m_Lock.ExitReadLock();
+			}
+
+			return null;
+		}
+
 
-		public UserDataDescriptor Descriptor { get; set; }
+		private static UserDataDescriptor GetDescriptorForObject(object o)
+		{
+			return GetDescriptorForType(o.GetType(), true);
+		}
 	}
 }

+ 38 - 0
src/MoonSharp.Interpreter/DataTypes/UserDataAccessMode.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter
+{
+	[Flags]
+	public enum UserDataAccessMode
+	{
+		/// <summary>
+		/// Optimization is not performed and reflection is used everytime to access members.
+		/// This is the slowest approach but saves a lot of memory if members are seldomly used.
+		/// </summary>
+		Reflection,
+		/// <summary>
+		/// Optimization is done on the fly the first time a member is accessed.
+		/// </summary>
+		LazyOptimized,
+		/// <summary>
+		/// Optimization is done at registration time
+		/// </summary>
+		Preoptimized,
+		/// <summary>
+		/// Optimization is done in a background thread which starts at registration time. 
+		/// If a member is accessed before optimization is completed, reflection is used.
+		/// </summary>
+		BackgroundOptimized,
+		/// <summary>
+		/// No optimization is done, and members are not accessible at all.
+		/// </summary>
+		HideMembers,
+		/// <summary>
+		/// Use the default access mode set in the registry
+		/// </summary>
+		Default
+	}
+}

+ 4 - 8
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs

@@ -4,6 +4,7 @@ using System.Linq;
 using System.Text;
 using MoonSharp.Interpreter.DataStructs;
 using MoonSharp.Interpreter.Debugging;
+using MoonSharp.Interpreter.Interop;
 
 namespace MoonSharp.Interpreter.Execution.VM
 {
@@ -370,7 +371,6 @@ namespace MoonSharp.Interpreter.Execution.VM
 			// Moon# additions - given f, s, var
 			// 1) if f is not a function and has a __iterator metamethod, call __iterator to get the triplet
 			// 2) if f is a table with no __call metamethod, use a default table iterator
-			// 3) if f is a userdata, call its descriptor Iterate method
 
 			if (f.Type != DataType.Function && f.Type != DataType.ClrFunction)
 			{
@@ -391,13 +391,9 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 					if (callmeta == null || callmeta.IsNil())
 					{
-						m_ValueStack.Push(GetIEnumerableIteratorHelper(f));
+						m_ValueStack.Push(EnumerableWrapper.ConvertTable(f.Table));
 					}
 				}
-				else if (f.Type == DataType.UserData)
-				{
-					m_ValueStack.Push(GetIEnumerableIteratorHelper(f));
-				}
 			}
 
 			m_ValueStack.Push(DynValue.NewTuple(f, s, var));
@@ -1038,7 +1034,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 					if (idx.Type != DataType.String)
 						throw ScriptRuntimeException.BadArgument(1, string.Format("userdata<{0}>.__newindex", ud.Descriptor.Name), "string", idx.Type.ToLuaTypeString(), false);
 
-					ud.Descriptor.SetIndex(ud.Object, idx.String, value);
+					ud.Descriptor.SetIndex(this.GetScript(), ud.Object, idx.String, value);
 					return instructionPtr;
 				}
 				else
@@ -1105,7 +1101,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 					if (idx.Type != DataType.String)
 						throw ScriptRuntimeException.BadArgument(1, string.Format("userdata<{0}>.__index", ud.Descriptor.Name), "string", idx.Type.ToLuaTypeString(), false);
 
-					var v = ud.Descriptor.Index(ud.Object, idx.String);
+					var v = ud.Descriptor.Index(this.GetScript(), ud.Object, idx.String);
 					m_ValueStack.Push(v.AsReadOnly());
 					return instructionPtr;
 				}

+ 1 - 4
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs

@@ -142,9 +142,6 @@ namespace MoonSharp.Interpreter.Execution.VM
 		}
 
 
-		private DynValue GetIEnumerableIteratorHelper(DynValue f)
-		{
-			return DynValue.Nil;
-		}
+
 	}
 }

+ 45 - 5
src/MoonSharp.Interpreter/Interop/ConversionHelper.cs

@@ -76,30 +76,70 @@ namespace MoonSharp.Interpreter.Interop
 
 			if (v != null) return v;
 
-			v = script.UserDataRepository.CreateUserData(obj);
+			v = UserData.Create(obj);
 
 			if (v != null) return v;
 
 			if (obj is Type)
+				v = UserData.CreateStatic(obj as Type);
+
+			if (v != null) return v;
+
+			if (obj is System.Collections.IList)
+			{
+				Table t = ConvertIListToTable(script, (System.Collections.IList)obj);
+				return DynValue.NewTable(t);
+			}
+
+			if (obj is System.Collections.IDictionary)
 			{
-				v = script.UserDataRepository.CreateStaticUserData(obj as Type);
+				Table t = ConvertIDictionaryToTable(script, (System.Collections.IDictionary)obj);
+				return DynValue.NewTable(t);
 			}
 
 			if (obj is System.Collections.IEnumerable)
 			{
 				var enumer = (System.Collections.IEnumerable)obj;
-				return EnumerableIterator.ConvertIterator(script, enumer.GetEnumerator());
+				return EnumerableWrapper.ConvertIterator(script, enumer.GetEnumerator());
 			}
 
 			if (obj is System.Collections.IEnumerator)
 			{
 				var enumer = (System.Collections.IEnumerator)obj;
-				return EnumerableIterator.ConvertIterator(script, enumer);
+				return EnumerableWrapper.ConvertIterator(script, enumer);
 			}
 
 			throw ScriptRuntimeException.ConvertObjectFailed(obj);
 		}
 
+		private static Table ConvertIDictionaryToTable(Script script, System.Collections.IDictionary dict)
+		{
+			Table t = new Table(script);
+			
+			foreach(System.Collections.DictionaryEntry kvp in dict)
+			{
+				DynValue key = ClrObjectToComplexMoonSharpValue(script, kvp.Key);
+				DynValue val = ClrObjectToComplexMoonSharpValue(script, kvp.Value);
+				t.Set(key, val);
+			}
+
+			return t;
+		}
+
+		private static Table ConvertIListToTable(Script script, System.Collections.IList list)
+		{
+			Table t = new Table(script);
+			for (int i = 0; i < list.Count; i++)
+			{
+				t[i + 1] = ClrObjectToComplexMoonSharpValue(script, list[i]);
+			}
+			return t;
+		}
+
+
+
+
+
 		internal static object MoonSharpValueToClrObject(DynValue value)
 		{
 			switch (value.Type)
@@ -261,7 +301,7 @@ namespace MoonSharp.Interpreter.Interop
 		{
 			Dictionary<TK, TV> dict = new Dictionary<TK, TV>();
 
-			foreach (var kvp in table.EnumerateKeyValuePairs())
+			foreach (var kvp in table.Pairs)
 			{
 				TK key = keyconverter(kvp.Key);
 				TV val = valconverter(kvp.Value);

+ 12 - 6
src/MoonSharp.Interpreter/Interop/EnumerableIterator.cs → src/MoonSharp.Interpreter/Interop/EnumerableWrapper.cs

@@ -7,13 +7,14 @@ using MoonSharp.Interpreter.Execution;
 
 namespace MoonSharp.Interpreter.Interop
 {
-	public class EnumerableIterator
+	public class EnumerableWrapper
 	{
 		IEnumerator m_Enumerator;
 		Script m_Script;
 		bool m_HasTurnOnce = false;
 
-		private EnumerableIterator(Script script, IEnumerator enumerator)
+
+		private EnumerableWrapper(Script script, IEnumerator enumerator)
 		{
 			m_Script = script;
 			m_Enumerator = enumerator;
@@ -49,13 +50,13 @@ namespace MoonSharp.Interpreter.Interop
 			DynValue prev = args[1];
 
 			UserData ud = userdata.UserData;
-			EnumerableIterator iterator = ud.Object as EnumerableIterator;
+			EnumerableWrapper iterator = ud.Object as EnumerableWrapper;
 
 			if (iterator == null)
 			{
 				throw ScriptRuntimeException.BadArgument(0, "clr_iterator_next",
 					(ud.Object != null) ? ud.Object.GetType().FullName : "null",
-					typeof(EnumerableIterator).FullName,
+					typeof(EnumerableWrapper).FullName,
 					false);
 			}
 
@@ -64,13 +65,18 @@ namespace MoonSharp.Interpreter.Interop
 
 		public static DynValue ConvertIterator(Script script, IEnumerator enumerator)
 		{
-			EnumerableIterator ei = new EnumerableIterator(script, enumerator);
+			EnumerableWrapper ei = new EnumerableWrapper(script, enumerator);
 
 			return DynValue.NewTuple(
 				DynValue.NewCallback(clr_iterator_next),
-				script.UserDataRepository.CreateUserData(ei),
+				UserData.Create(ei),
 				DynValue.Nil);
 		}
 
+		public static DynValue ConvertTable(Table table)
+		{
+			return ConvertIterator(table.OwnerScript, table.Values.GetEnumerator());
+		}
+
 	}
 }

+ 18 - 0
src/MoonSharp.Interpreter/Interop/MoonSharpUserDataAttribute.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Interop
+{
+	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+	public sealed class MoonSharpUserDataAttribute : Attribute
+	{
+		public UserDataAccessMode AccessMode { get; private set; }
+
+		public MoonSharpUserDataAttribute()
+		{
+			AccessMode = UserDataAccessMode.Default;
+		}
+	}
+}

+ 18 - 0
src/MoonSharp.Interpreter/Interop/MoonSharpVisibleAttribute.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Interop
+{
+	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
+	public sealed class MoonSharpVisibleAttribute : Attribute
+	{
+		public bool Visible { get; private set; }
+
+		public MoonSharpVisibleAttribute(bool visible)
+		{
+			Visible = visible;
+		}
+	}
+}

+ 40 - 21
src/MoonSharp.Interpreter/Interop/UserDataDescriptor.cs

@@ -3,65 +3,84 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
 using System.Text;
+using System.Threading;
 using MoonSharp.Interpreter.Execution;
 
 namespace MoonSharp.Interpreter.Interop
 {
-	public class UserDataDescriptor
+	internal class UserDataDescriptor
 	{
-		public string Name { get; private set; }
-		public Type Type { get; private set; }
-		public UserDataOptimizationMode OptimizationMode { get; private set; }
-		public UserDataRepository Repository { get; private set; }
+		internal string Name { get; private set; }
+		internal Type Type { get; private set; }
+		internal UserDataAccessMode AccessMode { get; private set; }
 
 		private Dictionary<string, UserDataMethodDescriptor> m_Methods = new Dictionary<string, UserDataMethodDescriptor>();
 		private Dictionary<string, UserDataPropertyDescriptor> m_Properties = new Dictionary<string, UserDataPropertyDescriptor>();
 
-		internal UserDataDescriptor(UserDataRepository repository, Type type, UserDataOptimizationMode optimizationMode)
+		internal UserDataDescriptor(Type type, UserDataAccessMode accessMode)
 		{
-			Repository = repository;
 			Type = type;
 			Name = type.FullName;
-			OptimizationMode = optimizationMode;
+			AccessMode = accessMode;
 
-			if (OptimizationMode != UserDataOptimizationMode.HideMembers)
+			if (AccessMode != UserDataAccessMode.HideMembers)
 			{
-				foreach (MethodInfo mi in type.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
+				foreach (MethodInfo mi in type.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Static))
 				{
-					var md = new UserDataMethodDescriptor(mi, this);
+					if (CheckVisibility(mi.GetCustomAttributes(true), mi.IsPublic))
+					{
+						if (mi.IsSpecialName)
+							continue;
 
-					if (m_Methods.ContainsKey(md.Name))
-						throw new ArgumentException(string.Format("{0}.{1} has overloads", Name, md.Name));
+						var md = new UserDataMethodDescriptor(mi, this);
 
-					m_Methods.Add(md.Name, md);
+						if (m_Methods.ContainsKey(md.Name))
+							throw new ArgumentException(string.Format("{0}.{1} has overloads", Name, md.Name));
+
+						m_Methods.Add(md.Name, md);
+					}
 				}
 
-				foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
+				foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Instance | BindingFlags.Static))
 				{
-					var pd = new UserDataPropertyDescriptor(pi, this);
-					m_Properties.Add(pd.Name, pd);
+					if (CheckVisibility(pi.GetCustomAttributes(true), pi.GetGetMethod().IsPublic || pi.GetSetMethod().IsPublic))
+					{
+						var pd = new UserDataPropertyDescriptor(pi, this);
+						m_Properties.Add(pd.Name, pd);
+					}
 				}
 			}
 		}
 
+		private bool CheckVisibility(object[] attributes, bool isPublic)
+		{
+			MoonSharpVisibleAttribute va = attributes.OfType<MoonSharpVisibleAttribute>().SingleOrDefault();
+
+			if (va != null)
+				return va.Visible;
+			else
+				return isPublic;
+		}
+
+
 
-		public DynValue Index(object obj, string idxname)
+		internal DynValue Index(Script script, object obj, string idxname)
 		{
 			if (m_Methods.ContainsKey(idxname))
 			{
-				return DynValue.NewCallback(m_Methods[idxname].GetCallback(obj));
+				return DynValue.NewCallback(m_Methods[idxname].GetCallback(script, obj));
 			}
 
 			if (m_Properties.ContainsKey(idxname))
 			{
 				object o = m_Properties[idxname].GetValue(obj);
-				return ConversionHelper.ClrObjectToComplexMoonSharpValue(this.Repository.OwnerScript, o);
+				return ConversionHelper.ClrObjectToComplexMoonSharpValue(script, o);
 			}
 
 			throw ScriptRuntimeException.UserDataMissingField(this.Name, idxname);
 		}
 
-		public void SetIndex(object obj, string idxname, DynValue value)
+		internal void SetIndex(Script script, object obj, string idxname, DynValue value)
 		{
 			if (m_Properties.ContainsKey(idxname))
 			{

+ 69 - 12
src/MoonSharp.Interpreter/Interop/UserDataMethodDescriptor.cs

@@ -1,21 +1,24 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Linq.Expressions;
 using System.Reflection;
 using System.Text;
 using MoonSharp.Interpreter.Execution;
 
 namespace MoonSharp.Interpreter.Interop
 {
-	public class UserDataMethodDescriptor
+	internal class UserDataMethodDescriptor
 	{
-		public MethodInfo MethodInfo { get; private set; }
-		public UserDataDescriptor UserDataDescriptor { get; private set; }
-		public bool IsStatic { get; private set; }
-		public string Name { get; private set; }
+		internal MethodInfo MethodInfo { get; private set; }
+		internal UserDataDescriptor UserDataDescriptor { get; private set; }
+		internal bool IsStatic { get; private set; }
+		internal string Name { get; private set; }
 
 		private Type[] m_Arguments;
 		private object[] m_Defaults;
+		private Func<object, object[], object> m_OptimizedFunc = null;
+		private Action<object, object[]> m_OptimizedAction = null;
 
 		internal UserDataMethodDescriptor(MethodInfo mi, UserDataDescriptor userDataDescriptor)
 		{
@@ -26,25 +29,79 @@ namespace MoonSharp.Interpreter.Interop
 
 			m_Arguments = mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
 			m_Defaults = mi.GetParameters().Select(pi => pi.DefaultValue).ToArray();
-		}
 
+			if (userDataDescriptor.AccessMode == UserDataAccessMode.Preoptimized)
+				Optimize();
+		}
 
-		internal Func<ScriptExecutionContext, CallbackArguments, DynValue> GetCallback(object obj)
+		internal Func<ScriptExecutionContext, CallbackArguments, DynValue> GetCallback(Script script, object obj)
 		{
-			return (c, a) => ReflectionCallback(obj, c, a);
+			return (c, a) => Callback(script, obj, c, a);
 		}
 
-		DynValue ReflectionCallback(object obj, ScriptExecutionContext context, CallbackArguments args)
+		DynValue Callback(Script script, object obj, ScriptExecutionContext context, CallbackArguments args)
 		{
+			if (UserDataDescriptor.AccessMode == UserDataAccessMode.LazyOptimized &&
+				m_OptimizedFunc == null && m_OptimizedAction == null)
+				Optimize();
+
 			object[] pars = new object[m_Arguments.Length];
-			
+
 			for (int i = 0; i < pars.Length; i++)
 			{
 				pars[i] = ConversionHelper.MoonSharpValueToObjectOfType(args[i], m_Arguments[i], m_Defaults[i]);
 			}
 
-			object retv = MethodInfo.Invoke(obj, pars);
-			return ConversionHelper.ClrObjectToComplexMoonSharpValue(this.UserDataDescriptor.Repository.OwnerScript, retv);
+
+			object retv = null;
+
+			if (m_OptimizedFunc != null)
+				retv = m_OptimizedFunc(obj, pars);
+			else if (m_OptimizedAction != null)
+				m_OptimizedAction(obj, pars);
+			else
+				retv = MethodInfo.Invoke(obj, pars);
+
+			return ConversionHelper.ClrObjectToComplexMoonSharpValue(script, retv);
+		}
+
+		private void Optimize()
+		{
+			var ep = Expression.Parameter(typeof(object[]), "pars");
+			var objinst = Expression.Parameter(typeof(object), "instance");
+			var inst = Expression.Convert(objinst, UserDataDescriptor.Type);
+
+			Expression[] args = new Expression[m_Arguments.Length];
+
+			for (int i = 0; i < m_Arguments.Length; i++)
+			{
+				var x = Expression.ArrayIndex(ep, Expression.Constant(i));
+				args[i] = Expression.Convert(x, m_Arguments[i]);
+			}
+
+			Expression fn;
+
+			if (IsStatic)
+			{
+				fn = Expression.Call(MethodInfo, args);
+			}
+			else
+			{
+				fn = Expression.Call(inst, MethodInfo, args);
+			}
+
+
+			if (MethodInfo.ReturnType == typeof(void))
+			{
+				var lambda = Expression.Lambda<Action<object, object[]>>(fn, objinst, ep);
+				m_OptimizedAction = lambda.Compile();
+			}
+			else
+			{
+				var fnc = Expression.Convert(fn, typeof(object));
+				var lambda = Expression.Lambda<Func<object, object[], object>>(fnc, objinst, ep);
+				m_OptimizedFunc = lambda.Compile();
+			}
 		}
 	}
 }

+ 0 - 17
src/MoonSharp.Interpreter/Interop/UserDataOptimizationMode.cs

@@ -1,17 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace MoonSharp.Interpreter.Interop
-{
-	[Flags]
-	public enum UserDataOptimizationMode
-	{
-		None,
-		Lazy,
-		Precomputed,
-		HideMembers,
-		Default
-	}
-}

+ 10 - 10
src/MoonSharp.Interpreter/Interop/UserDataPropertyDescriptor.cs

@@ -7,12 +7,12 @@ using System.Text;
 
 namespace MoonSharp.Interpreter.Interop
 {
-	public class UserDataPropertyDescriptor
+	internal class UserDataPropertyDescriptor
 	{
-		public PropertyInfo PropertyInfo { get; private set; }
-		public UserDataDescriptor UserDataDescriptor { get; private set; }
-		public bool IsStatic { get; private set; }
-		public string Name { get; private set; }
+		internal PropertyInfo PropertyInfo { get; private set; }
+		internal UserDataDescriptor UserDataDescriptor { get; private set; }
+		internal bool IsStatic { get; private set; }
+		internal string Name { get; private set; }
 
 		Func<object, object> m_OptimizedGetter = null;
 		Action<object, object> m_OptimizedSetter = null;
@@ -25,7 +25,7 @@ namespace MoonSharp.Interpreter.Interop
 			this.Name = pi.Name;
 			this.IsStatic = (this.PropertyInfo.GetGetMethod() ?? this.PropertyInfo.GetSetMethod()).IsStatic;
 
-			if (userDataDescriptor.OptimizationMode == UserDataOptimizationMode.Precomputed)
+			if (userDataDescriptor.AccessMode == UserDataAccessMode.Preoptimized)
 			{
 				this.OptimizeGetter();
 				this.OptimizeSetter();
@@ -33,9 +33,9 @@ namespace MoonSharp.Interpreter.Interop
 		}
 
 
-		public object GetValue(object obj)
+		internal object GetValue(object obj)
 		{
-			if (UserDataDescriptor.OptimizationMode == UserDataOptimizationMode.Lazy && m_OptimizedGetter == null)
+			if (UserDataDescriptor.AccessMode == UserDataAccessMode.LazyOptimized && m_OptimizedGetter == null)
 				OptimizeGetter();
 
 			if (m_OptimizedGetter != null)
@@ -96,14 +96,14 @@ namespace MoonSharp.Interpreter.Interop
 			}
 		}
 
-		public void SetValue(object obj, object value, DataType originalType)
+		internal void SetValue(object obj, object value, DataType originalType)
 		{
 			try
 			{
 				if (value is double)
 					value = ConversionHelper.DoubleToType(PropertyInfo.PropertyType, (double)value);
 
-				if (UserDataDescriptor.OptimizationMode == UserDataOptimizationMode.Lazy && m_OptimizedSetter == null)
+				if (UserDataDescriptor.AccessMode == UserDataAccessMode.LazyOptimized && m_OptimizedSetter == null)
 					OptimizeSetter();
 
 				if (m_OptimizedSetter != null)

+ 0 - 103
src/MoonSharp.Interpreter/Interop/UserDataRepository.cs

@@ -1,103 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace MoonSharp.Interpreter.Interop
-{
-	public class UserDataRepository
-	{
-		private Dictionary<Type, UserDataDescriptor> m_ByType = new Dictionary<Type, UserDataDescriptor>();
-		private Dictionary<string, UserDataDescriptor> m_ByName = new Dictionary<string, UserDataDescriptor>();
-
-		public Script OwnerScript { get; private set; }
-
-		internal UserDataRepository(Script script)
-		{
-			OwnerScript = script;
-			this.RegisterType<EnumerableIterator>(UserDataOptimizationMode.HideMembers);
-		}
-
-		public UserDataDescriptor RegisterType<T>(UserDataOptimizationMode optimizationMode = UserDataOptimizationMode.None)
-		{
-			return RegisterType(typeof(T), optimizationMode);
-		}
-
-
-		public UserDataDescriptor RegisterType(Type type, UserDataOptimizationMode optimizationMode = UserDataOptimizationMode.None)
-		{
-			if (m_ByType.ContainsKey(type))
-				return m_ByType[type];
-
-			UserDataDescriptor udd = new UserDataDescriptor(this, type, optimizationMode);
-			m_ByType.Add(udd.Type, udd);
-			m_ByName.Add(udd.Name, udd);
-			return udd;
-		}
-
-		public UserDataDescriptor GetDescriptorForType<T>(bool deepSearch = true)
-		{
-			return GetDescriptorForType(typeof(T), deepSearch);
-		}
-
-		public UserDataDescriptor GetDescriptorForType(Type type, bool deepSearch = true)
-		{
-			if (!deepSearch)
-				return m_ByType.ContainsKey(type) ? m_ByType[type] : null;
-
-			for (Type t = type; t != typeof(object); t = t.BaseType)
-			{
-				if (m_ByType.ContainsKey(t))
-					return m_ByType[t];
-			}
-
-			foreach (Type t in type.GetInterfaces())
-			{
-				if (m_ByType.ContainsKey(t))
-					return m_ByType[t];
-			}
-
-			if (m_ByType.ContainsKey(typeof(object)))
-				return m_ByType[type];
-
-			return null;
-		}
-
-		public UserDataDescriptor GetDescriptorForObject(object o)
-		{
-			return GetDescriptorForType(o.GetType(), true);
-		}
-
-		public DynValue CreateUserData(object o)
-		{
-			var descr = GetDescriptorForObject(o);
-			if (descr == null) return null;
-				
-			return DynValue.NewUserData(new UserData()
-				{
-					Descriptor = descr,
-					Object = o
-				});
-		}
-
-		public DynValue CreateStaticUserData(Type t)
-		{
-			var descr = GetDescriptorForType(t, false);
-			if (descr == null) return null;
-
-			return DynValue.NewUserData(new UserData()
-			{
-				Descriptor = descr,
-				Object = null
-			});
-		}
-
-		public DynValue CreateStaticUserData<T>()
-		{
-			return CreateStaticUserData(typeof(T));
-		}
-
-
-
-	}
-}

+ 7 - 6
src/MoonSharp.Interpreter/MoonSharp.Interpreter.csproj

@@ -100,7 +100,9 @@
     <Compile Include="DataStructs\Slice.cs" />
     <Compile Include="DataTypes\IScriptPrivateResource.cs" />
     <Compile Include="DataTypes\TailCallData.cs" />
-    <Compile Include="DataTypes\UserData.cs" />
+    <Compile Include="DataTypes\UserData.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="DataTypes\WellKnownSymbols.cs" />
     <Compile Include="Debugging\DebuggerAction.cs" />
     <Compile Include="Debugging\IDebugger.cs" />
@@ -133,16 +135,15 @@
     <Compile Include="Execution\VM\Processor\Processor_Errors.cs" />
     <Compile Include="Interface\IteratorHelper.cs" />
     <Compile Include="Interop\ConversionHelper.cs" />
-    <Compile Include="Interop\EnumerableIterator.cs">
-      <SubType>Code</SubType>
-    </Compile>
+    <Compile Include="Interop\EnumerableWrapper.cs" />
+    <Compile Include="Interop\MoonSharpUserDataAttribute.cs" />
+    <Compile Include="Interop\MoonSharpVisibleAttribute.cs" />
     <Compile Include="Interop\UserDataDescriptor.cs" />
-    <Compile Include="Interop\UserDataOptimizationMode.cs" />
+    <Compile Include="DataTypes\UserDataAccessMode.cs" />
     <Compile Include="Interop\UserDataMethodDescriptor.cs" />
     <Compile Include="Interop\UserDataPropertyDescriptor.cs">
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Interop\UserDataRepository.cs" />
     <Compile Include="Loaders\ClassicLuaScriptLoader.cs" />
     <Compile Include="Loaders\IScriptLoader.cs" />
     <Compile Include="Execution\Scopes\ClosureContext.cs" />

+ 0 - 6
src/MoonSharp.Interpreter/Script.cs

@@ -53,7 +53,6 @@ namespace MoonSharp.Interpreter
 		{
 			DebugPrint = s => { Console.WriteLine(s); };
 			m_ByteCode = new ByteCode();
-			UserDataRepository = new UserDataRepository(this);
 			m_GlobalTable = new Table(this).RegisterCoreModules(coreModules);
 			m_MainRoutine = new Processor(this, m_GlobalTable, m_ByteCode);
 			ReseedRandomGenerator(DateTime.Now.Millisecond);
@@ -79,11 +78,6 @@ namespace MoonSharp.Interpreter
 		/// </summary>
 		public static IScriptLoader DefaultScriptLoader { get; set; }
 
-		/// <summary>
-		/// Gets the userdata type repository.
-		/// </summary>
-		public UserDataRepository UserDataRepository { get; private set; }
-
 		/// <summary>
 		/// Gets the default global table for this script. Unless a different table is intentionally passed (or setfenv has been used)
 		/// execution uses this table.

+ 1 - 1
src/MoonSharpTests/Program.cs

@@ -67,7 +67,7 @@ namespace MoonSharpTests
 			}
 			catch (Exception ex)
 			{
-				Console.WriteLine(" failed: {0} ", ex.InnerException.Message);
+				Console.WriteLine(" failed - {0}", ex.InnerException.Message);
 				return false;
 			}
 		}