Browse Source

Simplified table syntax + slow method marshalling

Xanathar 11 years ago
parent
commit
7f628fac06
31 changed files with 697 additions and 350 deletions
  1. 1 1
      src/MoonSharp.Debugger/MainForm.cs
  2. 15 15
      src/MoonSharp.Interpreter.Tests/EndToEnd/LuaTestSuiteExtract.cs
  3. 17 17
      src/MoonSharp.Interpreter.Tests/EndToEnd/SimpleTests.cs
  4. 3 3
      src/MoonSharp.Interpreter.Tests/EndToEnd/TailCallTests.cs
  5. 84 0
      src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataMethodsTests.cs
  6. 34 13
      src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataPropertiesTests.cs
  7. 1 0
      src/MoonSharp.Interpreter.Tests/MoonSharp.Interpreter.Tests.csproj
  8. 1 1
      src/MoonSharp.Interpreter.Tests/TestMore/TapRunner.cs
  9. 3 3
      src/MoonSharp.Interpreter/CoreLib/MetaTableMethods.cs
  10. 8 8
      src/MoonSharp.Interpreter/CoreLib/Patterns/PatternMatching.cs
  11. 1 1
      src/MoonSharp.Interpreter/CoreLib/StringModule.cs
  12. 1 1
      src/MoonSharp.Interpreter/CoreLib/TableIterators.cs
  13. 10 10
      src/MoonSharp.Interpreter/CoreLib/TableModule.cs
  14. 10 0
      src/MoonSharp.Interpreter/DataTypes/DynValue.cs
  15. 99 72
      src/MoonSharp.Interpreter/DataTypes/Table.cs
  16. 5 0
      src/MoonSharp.Interpreter/Errors/ScriptRuntimeException.cs
  17. 2 2
      src/MoonSharp.Interpreter/Execution/ExecutionContext.cs
  18. 41 16
      src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs
  19. 2 2
      src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Scope.cs
  20. 6 0
      src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs
  21. 309 0
      src/MoonSharp.Interpreter/Interop/ConversionHelper.cs
  22. 0 161
      src/MoonSharp.Interpreter/Interop/Converter.cs
  23. 1 1
      src/MoonSharp.Interpreter/Interop/EnumerableIterator.cs
  24. 2 2
      src/MoonSharp.Interpreter/Interop/UserDataDescriptor.cs
  25. 20 1
      src/MoonSharp.Interpreter/Interop/UserDataMethodDescriptor.cs
  26. 2 1
      src/MoonSharp.Interpreter/Interop/UserDataOptimizationMode.cs
  27. 1 1
      src/MoonSharp.Interpreter/Interop/UserDataPropertyDescriptor.cs
  28. 13 13
      src/MoonSharp.Interpreter/Modules/ModuleRegister.cs
  29. 1 1
      src/MoonSharp.Interpreter/MoonSharp.Interpreter.csproj
  30. 2 2
      src/MoonSharp/Program.cs
  31. 2 2
      src/PerformanceComparison/Program.cs

+ 1 - 1
src/MoonSharp.Debugger/MainForm.cs

@@ -87,7 +87,7 @@ namespace MoonSharp.Debugger
 
 			m_Script.DebugPrint = s => { Console_WriteLine("{0}", s); };
 			//m_Script.Globals["assert"] = DynValue.NewCallback(Assert);
-			m_Script.Globals["xassert"] = DynValue.NewCallback(XAssert);
+			m_Script.Globals.Set("xassert", DynValue.NewCallback(XAssert));
 
 			var L = new ClassicLuaScriptLoader();
 			L.ModulePaths = L.UnpackStringPaths("Modules/?;Modules/?.lua");

+ 15 - 15
src/MoonSharp.Interpreter.Tests/EndToEnd/LuaTestSuiteExtract.cs

@@ -22,30 +22,30 @@ namespace MoonSharp.Interpreter.Tests
 			Script S = new Script();
 
 			var globalCtx = S.Globals;
-			globalCtx[DynValue.NewString("xassert")] =  DynValue.NewCallback(new CallbackFunction(
+			globalCtx.Set(DynValue.NewString("xassert"), DynValue.NewCallback(new CallbackFunction(
 				(x, a) =>
 				{
 					if (!a[1].CastToBool())
 						failedTests.Add(a[0].String);
 
 					return DynValue.Nil;
-				}));
-			globalCtx[DynValue.NewString("assert")] =  DynValue.NewCallback(new CallbackFunction(
-			 (x, a) =>
-			 {
-				 ++i;
-
-				 if (!a[0].CastToBool())
-					 failedTests.Add(string.Format("assert #{0}", i));
+				})));
+			globalCtx.Set(DynValue.NewString("assert"), DynValue.NewCallback(new CallbackFunction(
+				(x, a) =>
+				{
+					++i;
 
-				 return DynValue.Nil;
-			 }));
+					if (!a[0].CastToBool())
+						failedTests.Add(string.Format("assert #{0}", i));
 
-			globalCtx[DynValue.NewString("print")] =  DynValue.NewCallback(new CallbackFunction((x, a) =>
-				{
-					// Debug.WriteLine(string.Join(" ", a.Select(v => v.AsString()).ToArray()));
 					return DynValue.Nil;
-				}));
+				})));
+
+			globalCtx.Set(DynValue.NewString("print"), DynValue.NewCallback(new CallbackFunction((x, a) =>
+			{
+				// Debug.WriteLine(string.Join(" ", a.Select(v => v.AsString()).ToArray()));
+				return DynValue.Nil;
+			})));
 
 
 			DynValue res = S.DoString(script);

+ 17 - 17
src/MoonSharp.Interpreter.Tests/EndToEnd/SimpleTests.cs

@@ -19,11 +19,11 @@ namespace MoonSharp.Interpreter.Tests
 
 			Script S = new Script();
 
-			S.Globals["print"] = DynValue.NewCallback(new CallbackFunction((x, a) => 
+			S.Globals.Set("print", DynValue.NewCallback(new CallbackFunction((x, a) => 
 			{
 				args = a.ToArray();
 				return DynValue.NewNumber(1234.0); 
-			}));
+			})));
 
 			DynValue res = S.DoString(script);
 
@@ -43,7 +43,7 @@ namespace MoonSharp.Interpreter.Tests
 			string script = "local print = print; print(\"hello\", \"world\");";
 
 			var S = new Script();
-			S.Globals["print"] = DynValue.NewCallback(new CallbackFunction((_x, a) => { args = a.ToArray(); return DynValue.NewNumber(1234.0); }));
+			S.Globals.Set("print", DynValue.NewCallback(new CallbackFunction((_x, a) => { args = a.ToArray(); return DynValue.NewNumber(1234.0); })));
 
 			DynValue res = S.DoString(script);
 
@@ -63,7 +63,7 @@ namespace MoonSharp.Interpreter.Tests
 			string script = "return print(\"hello\", \"world\");";
 
 			var S = new Script();
-			S.Globals["print"] = DynValue.NewCallback(new CallbackFunction((_x, a) => { args = a.ToArray(); return DynValue.NewNumber(1234.0); }));
+			S.Globals.Set("print", DynValue.NewCallback(new CallbackFunction((_x, a) => { args = a.ToArray(); return DynValue.NewNumber(1234.0); })));
 
 			DynValue res = S.DoString(script);
 
@@ -122,10 +122,10 @@ namespace MoonSharp.Interpreter.Tests
 			";
 
 			Script S = new Script();
-			S.Globals["crash"] = DynValue.NewCallback(new CallbackFunction((_x, a) =>
+			S.Globals.Set("crash", DynValue.NewCallback(new CallbackFunction((_x, a) =>
 			{
 				throw new Exception("FAIL!");
-			}));
+			})));
 
 			S.DoString(script);
 		}
@@ -936,22 +936,22 @@ namespace MoonSharp.Interpreter.Tests
 
 			Table T = res.Table;
 
-			Assert.AreEqual(DataType.Boolean, T["T1"].Type, "T1-Type");
-			Assert.AreEqual(true, T["T1"].Boolean, "T1-Val");
+			Assert.AreEqual(DataType.Boolean, T.Get("T1").Type, "T1-Type");
+			Assert.AreEqual(true, T.Get("T1").Boolean, "T1-Val");
 
-			Assert.AreEqual(DataType.Boolean, T["T2"].Type, "T2-Type");
-			Assert.AreEqual(true, T["T2"].Boolean, "T2-Val");
+			Assert.AreEqual(DataType.Boolean, T.Get("T2").Type, "T2-Type");
+			Assert.AreEqual(true, T.Get("T2").Boolean, "T2-Val");
 
-			Assert.AreEqual(DataType.Number, T["T3"].Type, "T3-Type");
-			Assert.AreEqual(1, T["T3"].Number, "T3-Val");
+			Assert.AreEqual(DataType.Number, T.Get("T3").Type, "T3-Type");
+			Assert.AreEqual(1, T.Get("T3").Number, "T3-Val");
 
-			Assert.AreEqual(DataType.Nil, T["T4"].Type, "T4");
+			Assert.AreEqual(DataType.Nil, T.Get("T4").Type, "T4");
 
-			Assert.AreEqual(DataType.Number, T["T5"].Type, "T5-Type");
-			Assert.AreEqual(2, T["T5"].Number, "T5-Val");
+			Assert.AreEqual(DataType.Number, T.Get("T5").Type, "T5-Type");
+			Assert.AreEqual(2, T.Get("T5").Number, "T5-Val");
 
-			Assert.AreEqual(DataType.Number, T["T6"].Type, "T6-Type");
-			Assert.AreEqual(3, T["T6"].Number, "T6-Val");
+			Assert.AreEqual(DataType.Number, T.Get("T6").Type, "T6-Type");
+			Assert.AreEqual(3, T.Get("T6").Number, "T6-Val");
 		}
 
 

+ 3 - 3
src/MoonSharp.Interpreter.Tests/EndToEnd/TailCallTests.cs

@@ -23,13 +23,13 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			Script S = new Script();
 
-			S.Globals["clrtail"] = DynValue.NewCallback((xc, a) =>
+			S.Globals.Set("clrtail", DynValue.NewCallback((xc, a) =>
 			{
-				DynValue fn = S.Globals["getResult"];
+				DynValue fn = S.Globals.Get("getResult");
 				DynValue k3 = DynValue.NewNumber(a[0].Number / 3);
 
 				return DynValue.NewTailCallReq(fn, k3);
-			});
+			}));
 
 			var res = S.DoString(script);
 

+ 84 - 0
src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataMethodsTests.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MoonSharp.Interpreter.Interop;
+using NUnit.Framework;
+
+namespace MoonSharp.Interpreter.Tests.EndToEnd
+{
+	[TestFixture]
+	public class UserDataMethodsTests
+	{
+		public class SomeClass : IComparable
+		{
+			public StringBuilder Concat(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);
+				p7.Append(p2);
+				p7.Append(p3);
+				p7.Append(p4);
+
+				p7.Append("|");
+				foreach (var o in p5) p7.Append(o);
+				p7.Append("|");
+				foreach (var o in p6) p7.Append(o);
+				p7.Append("|");
+				foreach (var o in p8.Keys.OrderBy(x => x.ToString())) p7.Append(o);
+				p7.Append("|");
+				foreach (var o in p8.Values.OrderBy(x => x.ToString())) p7.Append(o);
+				p7.Append("|");
+
+				p7.Append(p9);
+				p7.Append(p10);
+
+				return p7;
+			}
+
+			public override string ToString()
+			{
+				return "!SOMECLASS!";
+			}
+
+
+			public int CompareTo(object obj)
+			{
+				throw new NotImplementedException();
+			}
+		}
+
+
+		public void Test_ConcatMethod(UserDataOptimizationMode opt)
+		{
+			string script = @"    
+				t = { 'asd', 'qwe', 'zxc', ['x'] = 'X', ['y'] = 'Y' };
+				x = myobj.Concat(1, 'ciao', myobj, true, t, t, 'eheh', t, myobj);
+				return x;";
+
+			Script S = new Script();
+
+			SomeClass obj = new SomeClass();
+
+			S.UserDataRepository.RegisterType<SomeClass>(opt);
+
+			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(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);
+		}
+
+		[Test]
+		public void Interpo_ConcatMethod_None()
+		{
+			Test_ConcatMethod(UserDataOptimizationMode.None);
+		}
+
+	}
+}

+ 34 - 13
src/MoonSharp.Interpreter.Tests/EndToEnd/UserDataPropertiesTests.cs

@@ -39,7 +39,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj"] = S.UserDataRepository.CreateUserData(obj);
+			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
 
 			DynValue res = S.DoString(script);
 
@@ -61,8 +61,8 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj1"] = S.UserDataRepository.CreateUserData(obj1);
-			S.Globals["myobj2"] = S.UserDataRepository.CreateUserData(obj2);
+			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
+			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
 
 			DynValue res = S.DoString(script);
 
@@ -87,8 +87,8 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj1"] = S.UserDataRepository.CreateUserData(obj1);
-			S.Globals["myobj2"] = S.UserDataRepository.CreateUserData(obj2);
+			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
+			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
 
 			DynValue res = S.DoString(script);
 
@@ -112,7 +112,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj"] = S.UserDataRepository.CreateUserData(obj);
+			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
 
 			Assert.AreEqual(321, obj.IntProp);
 
@@ -134,8 +134,8 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj1"] = S.UserDataRepository.CreateUserData(obj1);
-			S.Globals["myobj2"] = S.UserDataRepository.CreateUserData(obj2);
+			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
+			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
 
 			Assert.AreEqual(321, obj1.NIntProp);
 			Assert.AreEqual(null, obj2.NIntProp);
@@ -159,8 +159,8 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj1"] = S.UserDataRepository.CreateUserData(obj1);
-			S.Globals["myobj2"] = S.UserDataRepository.CreateUserData(obj2);
+			S.Globals.Set("myobj1", S.UserDataRepository.CreateUserData(obj1));
+			S.Globals.Set("myobj2", S.UserDataRepository.CreateUserData(obj2));
 
 			Assert.AreEqual("ciao", obj1.ObjProp);
 			Assert.AreEqual(obj1, obj2.ObjProp);
@@ -182,7 +182,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj"] = S.UserDataRepository.CreateUserData(obj);
+			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
 
 			Assert.AreEqual(321, obj.IntProp);
 
@@ -202,7 +202,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["static"] = S.UserDataRepository.CreateStaticUserData<SomeClass>();
+			S.Globals.Set("static", S.UserDataRepository.CreateStaticUserData<SomeClass>());
 
 			Assert.AreEqual("qweqwe", SomeClass.StaticProp);
 
@@ -227,7 +227,7 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 
 			S.UserDataRepository.RegisterType<SomeClass>(opt);
 
-			S.Globals["myobj"] = S.UserDataRepository.CreateUserData(obj);
+			S.Globals.Set("myobj", S.UserDataRepository.CreateUserData(obj));
 
 			DynValue res = S.DoString(script);
 
@@ -402,5 +402,26 @@ namespace MoonSharp.Interpreter.Tests.EndToEnd
 			Test_IteratorPropertyGetter(UserDataOptimizationMode.Precomputed);
 		}
 
+		[Test]
+		public void Interop_IntPropertySetterWithSimplifiedSyntax()
+		{
+			string script = @"    
+				myobj.IntProp = 19;";
+
+			Script S = new Script();
+
+			SomeClass obj = new SomeClass() { IntProp = 321 };
+
+			S.UserDataRepository.RegisterType<SomeClass>();
+
+			S.Globals["myobj"] = obj;
+
+			Assert.AreEqual(321, obj.IntProp);
+
+			DynValue res = S.DoString(script);
+
+			Assert.AreEqual(obj, S.Globals["myobj"]);
+			Assert.AreEqual(19, obj.IntProp);
+		}
 	}
 }

+ 1 - 0
src/MoonSharp.Interpreter.Tests/MoonSharp.Interpreter.Tests.csproj

@@ -79,6 +79,7 @@
     </Compile>
     <Compile Include="EndToEnd\StringLibTests.cs" />
     <Compile Include="EndToEnd\TailCallTests.cs" />
+    <Compile Include="EndToEnd\UserDataMethodsTests.cs" />
     <Compile Include="EndToEnd\UserDataPropertiesTests.cs">
       <SubType>Code</SubType>
     </Compile>

+ 1 - 1
src/MoonSharp.Interpreter.Tests/TestMore/TapRunner.cs

@@ -30,7 +30,7 @@ namespace MoonSharp.Interpreter.Tests
 
 			//S.Globals["print"] = DynValue.NewCallback(Print);
 			S.DebugPrint = Print;
-			S.Globals["arg"] = DynValue.NewTable(S);
+			S.Globals.Set("arg", DynValue.NewTable(S));
 
 			var L = new ClassicLuaScriptLoader();
 			L.ModulePaths = L.UnpackStringPaths("TestMore/Modules/?;TestMore/Modules/?.lua");

+ 3 - 3
src/MoonSharp.Interpreter/CoreLib/MetaTableMethods.cs

@@ -56,7 +56,7 @@ namespace MoonSharp.Interpreter.CoreLib
 			if (meta == null)
 				return DynValue.Nil;
 			else if (meta.RawGet("__metatable") != null)
-				return meta["__metatable"];
+				return meta.Get("__metatable");
 			else
 				return DynValue.NewTable(meta);
 		}
@@ -70,7 +70,7 @@ namespace MoonSharp.Interpreter.CoreLib
 			DynValue table = args.AsType(0, "rawget", DataType.Table);
 			DynValue index = args[1];
 
-			return table.Table[index];
+			return table.Table.Get(index);
 		}
 
 		// rawset (table, index, value)
@@ -84,7 +84,7 @@ namespace MoonSharp.Interpreter.CoreLib
 			DynValue table = args.AsType(0, "rawset", DataType.Table);
 			DynValue index = args[1];
 
-			table.Table[index] = args[2];
+			table.Table.Set(index, args[2]);
 
 			return table;
 		}

+ 8 - 8
src/MoonSharp.Interpreter/CoreLib/Patterns/PatternMatching.cs

@@ -481,9 +481,9 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 
 		private static DynValue GmatchAux(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
-			DynValue v_idx = executionContext.Closure["idx"];
-			DynValue v_src = executionContext.Closure["src"];
-			DynValue v_pattern = executionContext.Closure["pattern"];
+			DynValue v_idx = executionContext.Closure.Get("idx");
+			DynValue v_src = executionContext.Closure.Get("src");
+			DynValue v_pattern = executionContext.Closure.Get("pattern");
 
 			MatchState ms = new MatchState();
 			string src = v_src.String;
@@ -501,7 +501,7 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 				if (e != -1)
 				{
 					int newStart = (e == 0) ? e + 1 : e;
-					executionContext.Closure["idx"] = DynValue.NewNumber(newStart);
+					executionContext.Closure.Set("idx", DynValue.NewNumber(newStart));
 					return PushCaptures(ms, s, e);
 				}
 			}
@@ -514,9 +514,9 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 			DynValue aux = DynValue.NewCallback(GmatchAux);
 
 			aux.Callback.Closure = new Table(script);
-			aux.Callback.Closure["idx"] = DynValue.NewNumber(0);
-			aux.Callback.Closure["src"] = DynValue.NewString(src);
-			aux.Callback.Closure["pattern"] = DynValue.NewString(pattern);
+			aux.Callback.Closure.Set("idx", DynValue.NewNumber(0));
+			aux.Callback.Closure.Set("src", DynValue.NewString(src));
+			aux.Callback.Closure.Set("pattern", DynValue.NewString(pattern));
 
 			return aux;
 		}
@@ -573,7 +573,7 @@ namespace MoonSharp.Interpreter.CoreLib.Patterns
 				case DataType.Table:
 					{
 						var v = PushOneCapture(ms, 0, s, e);
-						result = repl.Table[v];
+						result = repl.Table.Get(v);
 						break;
 					}
 			}

+ 1 - 1
src/MoonSharp.Interpreter/CoreLib/StringModule.cs

@@ -13,7 +13,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		public static void MoonSharpInit(Table globalTable, Table stringTable)
 		{
 			Table stringMetatable = new Table(globalTable.OwnerScript);
-			stringMetatable["__index"] = DynValue.NewTable(stringTable);
+			stringMetatable.Set("__index", DynValue.NewTable(stringTable));
 			globalTable.OwnerScript.SetTypeMetatable(DataType.String, stringMetatable);
 		}
 

+ 1 - 1
src/MoonSharp.Interpreter/CoreLib/TableIterators.cs

@@ -73,7 +73,7 @@ namespace MoonSharp.Interpreter.CoreLib
 			DynValue index = args.AsType(1, "!!next_i!!", DataType.Number);
 
 			int idx = ((int)index.Number) + 1;
-			DynValue val = table.Table[idx];
+			DynValue val = table.Table.Get(idx);
 			
 			if (val.Type != DataType.Nil)
 			{

+ 10 - 10
src/MoonSharp.Interpreter/CoreLib/TableModule.cs

@@ -26,7 +26,7 @@ namespace MoonSharp.Interpreter.CoreLib
 
 			int tidx = 1;
 			for (int i = ii; i <= ij; i++)
-				v[tidx++] = t[i];
+				v[tidx++] = t.Get(i);
 
 			return DynValue.NewTuple(v);
 		}
@@ -38,9 +38,9 @@ namespace MoonSharp.Interpreter.CoreLib
 			DynValue v = DynValue.NewTable(t);
 
 			for (int i = 0; i < args.Count; i++)
-				t[i + 1] = args[i];
+				t.Set(i + 1, args[i]);
 
-			t["n"] = DynValue.NewNumber(args.Count);
+			t.Set("n", DynValue.NewNumber(args.Count));
 
 			return v;
 		}
@@ -59,13 +59,13 @@ namespace MoonSharp.Interpreter.CoreLib
 			List<DynValue> values = new List<DynValue>();
 
 			for (int i = 1; i <= end; i++)
-				values.Add(vlist.Table[i]);
+				values.Add(vlist.Table.Get(i));
 
 			values.Sort((a, b) => SortComparer(executionContext, a, b, lt));
 
 			for (int i = 0; i < values.Count; i++)
 			{
-				vlist.Table[i + 1] = values[i];
+				vlist.Table.Set(i + 1, values[i]);
 			}
 
 			return vlist;
@@ -143,10 +143,10 @@ namespace MoonSharp.Interpreter.CoreLib
 
 			for (int i = len; i >= pos; i--)
 			{
-				list[i + 1] = list[i];
+				list.Set(i + 1, list.Get(i));
 			}
 
-			list[pos] = vvalue;
+			list.Set(pos, vvalue);
 
 			return vlist;
 		}
@@ -173,9 +173,9 @@ namespace MoonSharp.Interpreter.CoreLib
 			for (int i = pos; i <= len; i++)
 			{
 				if (i == pos)
-					ret = list[i];
+					ret = list.Get(i);
 
-				list[i] = list[i + 1];
+				list.Set(i, list.Get(i + 1));
 			}
 
 			return ret;
@@ -215,7 +215,7 @@ namespace MoonSharp.Interpreter.CoreLib
 
 			for (int i = start; i <= end; i++)
 			{
-				DynValue v = list[i];
+				DynValue v = list.Get(i);
 
 				if (v.Type != DataType.Number && v.Type != DataType.String)
 					throw new ScriptRuntimeException("invalid value ({1}) at index {0} in table for 'concat'", i, v.Type.ToLuaTypeString());

+ 10 - 0
src/MoonSharp.Interpreter/DataTypes/DynValue.cs

@@ -625,6 +625,16 @@ namespace MoonSharp.Interpreter
 			this.m_Number = num;
 		}
 
+
+		public static DynValue FromObject(Script s, object obj)
+		{
+			return MoonSharp.Interpreter.Interop.ConversionHelper.ClrObjectToComplexMoonSharpValue(s, obj);
+		}
+
+		public object ToObject()
+		{
+			return MoonSharp.Interpreter.Interop.ConversionHelper.MoonSharpValueToClrObject(this);
+		}
 	}
 
 

+ 99 - 72
src/MoonSharp.Interpreter/DataTypes/Table.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -9,11 +10,11 @@ namespace MoonSharp.Interpreter
 {
 	public class Table : IScriptPrivateResource
 	{
-		LinkedList<TablePair> m_Values;
-		LinkedListIndex<DynValue, TablePair> m_ValueMap;
-		LinkedListIndex<string, TablePair> m_StringMap;
-		LinkedListIndex<int, TablePair> m_ArrayMap;
-		Script m_Owner;
+		readonly LinkedList<TablePair> m_Values;
+		readonly LinkedListIndex<DynValue, TablePair> m_ValueMap;
+		readonly LinkedListIndex<string, TablePair> m_StringMap;
+		readonly LinkedListIndex<int, TablePair> m_ArrayMap;
+		readonly Script m_Owner;
 
 		int m_InitArray = 0;
 		int m_CachedLength = -1;
@@ -26,6 +27,7 @@ namespace MoonSharp.Interpreter
 			m_ValueMap = new LinkedListIndex<DynValue, TablePair>(m_Values);
 			m_Owner = owner;
 		}
+
 		public Script OwnerScript
 		{
 			get { return m_Owner; }
@@ -41,58 +43,84 @@ namespace MoonSharp.Interpreter
 			return -1;
 		}
 
-		public DynValue this[DynValue key]
+		public object this[object key]
 		{
-			get 
+			get
 			{
-				if (key.Type == DataType.Number)
-				{
-					int idx = GetIntegralKey(key.Number);
-					if (idx > 0)
-					{
-						return GetValueOrNil(m_ArrayMap.Find(idx));
-					}
-				}
-				else if (key.Type == DataType.String)
-				{
-					return GetValueOrNil(m_StringMap.Find(key.String));
-				}
+				if (key is string)
+					return Get((string)key).ToObject();
+				else if (key is int)
+					return Get((int)key).ToObject();
+				
+				DynValue dynkey = DynValue.FromObject(this.OwnerScript, key);
+				return Get(dynkey).ToObject();
+			}
+
+			set
+			{
+				DynValue dynval = DynValue.FromObject(this.OwnerScript, value);
 
-				return GetValueOrNil(m_ValueMap.Find(key));
+				if (key is string)
+					Set((string)key, dynval);
+				else if (key is int)
+					Set((int)key, dynval);
+				else
+					Set(DynValue.FromObject(this.OwnerScript, key), dynval);
 			}
-			set 
+		}
+
+
+
+		public void Set(DynValue key, DynValue value)
+		{
+			if (key.IsNilOrNan())
 			{
-				if (key.IsNilOrNan())
-				{
-					if (key.IsNil())
-						throw ScriptRuntimeException.TableIndexIsNil();
-					else
-						throw ScriptRuntimeException.TableIndexIsNaN();
-				}
+				if (key.IsNil())
+					throw ScriptRuntimeException.TableIndexIsNil();
+				else
+					throw ScriptRuntimeException.TableIndexIsNaN();
+			}
+
+			if (key.Type == DataType.String)
+			{
+				Set(key.String, value);
+				return;
+			}
+
+			if (key.Type == DataType.Number)
+			{
+				int idx = GetIntegralKey(key.Number);
 
-				if (key.Type == DataType.String)
+				if (idx > 0)
 				{
-					this[key.String] = value;
+					Set(idx, value);
 					return;
 				}
+			}
 
-				if (key.Type == DataType.Number)
-				{
-					int idx = GetIntegralKey(key.Number);
-
-					if (idx > 0)
-					{
-						this[idx] = value;
-						return;
-					}
-				}
+			CheckValueOwner(key);
+			CheckValueOwner(value);
 
-				CheckValueOwner(key);
-				CheckValueOwner(value);
+			if (m_ValueMap.Set(key, new TablePair(key, value)))
+				CollectDeadKeys();
+		}
 
-				if (m_ValueMap.Set(key, new TablePair(key, value)))
-					CollectDeadKeys();
+		public DynValue Get(DynValue key)
+		{
+			if (key.Type == DataType.Number)
+			{
+				int idx = GetIntegralKey(key.Number);
+				if (idx > 0)
+				{
+					return GetValueOrNil(m_ArrayMap.Find(idx));
+				}
 			}
+			else if (key.Type == DataType.String)
+			{
+				return GetValueOrNil(m_StringMap.Find(key.String));
+			}
+
+			return GetValueOrNil(m_ValueMap.Find(key));
 		}
 
 		private DynValue GetValueOrNil(LinkedListNode<TablePair> linkedListNode)
@@ -103,19 +131,17 @@ namespace MoonSharp.Interpreter
 			return DynValue.Nil;
 		}
 
-		public DynValue this[string key]
+		public void Set(string key, DynValue value)
 		{
-			get
-			{
-				return GetValueOrNil(m_StringMap.Find(key));
-			}
-			set
-			{
-				CheckValueOwner(value);
+			CheckValueOwner(value);
 
-				if (m_StringMap.Set(key, new TablePair(DynValue.NewString(key), value)))
-					CollectDeadKeys();
-			}
+			if (m_StringMap.Set(key, new TablePair(DynValue.NewString(key), value)))
+				CollectDeadKeys();
+		}
+
+		public DynValue Get(string key)
+		{
+			return GetValueOrNil(m_StringMap.Find(key));
 		}
 
 
@@ -129,24 +155,22 @@ namespace MoonSharp.Interpreter
 			return null;
 		}
 
-		public DynValue this[int key]
+		public void Set(int key, DynValue value)
 		{
-			get
+			CheckValueOwner(value);
+
+			if (m_ArrayMap.Set(key, new TablePair(DynValue.NewNumber(key), value)))
 			{
-				return GetValueOrNil(m_ArrayMap.Find(key));
+				CollectDeadKeys();
+				m_CachedLength = -1;
 			}
-			set
-			{
-				CheckValueOwner(value);
+			else if (value.IsNil())
+				m_CachedLength = -1;
+		}
 
-				if (m_ArrayMap.Set(key, new TablePair(DynValue.NewNumber(key), value)))
-				{
-					CollectDeadKeys();
-					m_CachedLength = -1;
-				}
-				else if (value.IsNil())
-					m_CachedLength = -1;
-			}
+		public DynValue Get(int key)
+		{
+			return GetValueOrNil(m_ArrayMap.Find(key));
 		}
 
 		private void CheckValueOwner(DynValue value)
@@ -231,7 +255,7 @@ namespace MoonSharp.Interpreter
 		}
 
 
-		public double Length
+		public int Length
 		{
 			get 
 			{
@@ -256,7 +280,7 @@ namespace MoonSharp.Interpreter
 			}
 			else
 			{
-				this[++m_InitArray] = val.ToScalar();
+				Set(++m_InitArray, val.ToScalar());
 			}
 		}
 
@@ -266,8 +290,11 @@ namespace MoonSharp.Interpreter
 		public Table MetaTable { get; set; }
 
 
-		
 
+		public IEnumerable<KeyValuePair<DynValue, DynValue>> EnumerateKeyValuePairs()
+		{
+			return m_Values.Select(n => new KeyValuePair<DynValue, DynValue>(n.Key, n.Value));
+		}
 		
 
 

+ 5 - 0
src/MoonSharp.Interpreter/Errors/ScriptRuntimeException.cs

@@ -119,6 +119,11 @@ namespace MoonSharp.Interpreter
 			return new ScriptRuntimeException("cannot convert a {0} to a clr type", t.ToString().ToLowerInvariant());
 		}
 
+		public static ScriptRuntimeException ConvertObjectFailed(DataType t, Type t2)
+		{
+			return new ScriptRuntimeException("cannot convert a {0} to a clr type {1}", t.ToString().ToLowerInvariant(), t2.FullName);
+		}
+
 		public static ScriptRuntimeException UserDataArgumentTypeMismatch(DataType t, Type clrType)
 		{
 			return new ScriptRuntimeException("cannot find a conversion from a moon# {0} to a clr {1}", t.ToString().ToLowerInvariant(), clrType.FullName);

+ 2 - 2
src/MoonSharp.Interpreter/Execution/ExecutionContext.cs

@@ -27,7 +27,7 @@ namespace MoonSharp.Interpreter.Execution
 		public DynValue GetVar(SymbolRef symref)
 		{
 			if (CheckUpValue(symref))
-				return m_Callback.Closure[symref.Name];
+				return m_Callback.Closure.Get(symref.Name);
 
 			return m_Processor.GetVar(symref);
 		}
@@ -35,7 +35,7 @@ namespace MoonSharp.Interpreter.Execution
 		public void SetVar(SymbolRef symref, DynValue value)
 		{
 			if (CheckUpValue(symref))
-				m_Callback.Closure[symref.Name] = value;
+				m_Callback.Closure.Set(symref.Name, value);
 
 			m_Processor.SetVar(symref, value);
 		}

+ 41 - 16
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs

@@ -362,20 +362,45 @@ namespace MoonSharp.Interpreter.Execution.VM
 			{
 				v = DynValue.NewTuple(v, DynValue.Nil, DynValue.Nil);
 			}
-			else if (v.Tuple.Length > 3)
-			{
-				v = DynValue.NewTuple(v.Tuple[0], v.Tuple[1], v.Tuple[2]);
-			}
-			else if (v.Tuple.Length == 2)
-			{
-				v = DynValue.NewTuple(v.Tuple[0], v.Tuple[1], DynValue.Nil);
-			}
-			else if (v.Tuple.Length == 1)
+
+			DynValue f = v.Tuple.Length >= 1 ? v.Tuple[0] : DynValue.Nil;
+			DynValue s = v.Tuple.Length >= 2 ? v.Tuple[1] : DynValue.Nil;
+			DynValue var = v.Tuple.Length >= 3 ? v.Tuple[2] : DynValue.Nil;
+
+			// 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)
 			{
-				v = DynValue.NewTuple(v.Tuple[0], DynValue.Nil, DynValue.Nil);
+				DynValue meta = this.GetMetamethod(f, "__iterator");
+
+				if (meta != null && !meta.IsNil())
+				{
+					v = this.GetScript().Call(meta, f, s, var);
+					f = v.Tuple.Length >= 1 ? v.Tuple[0] : DynValue.Nil;
+					s = v.Tuple.Length >= 2 ? v.Tuple[1] : DynValue.Nil;
+					var = v.Tuple.Length >= 3 ? v.Tuple[2] : DynValue.Nil;
+
+					m_ValueStack.Push(DynValue.NewTuple(f, s, var));
+				}
+				else if (f.Type == DataType.Table)
+				{
+					DynValue callmeta = this.GetMetamethod(f, "__call");
+
+					if (callmeta == null || callmeta.IsNil())
+					{
+						m_ValueStack.Push(GetIEnumerableIteratorHelper(f));
+					}
+				}
+				else if (f.Type == DataType.UserData)
+				{
+					m_ValueStack.Push(GetIEnumerableIteratorHelper(f));
+				}
 			}
 
-			m_ValueStack.Push(v);
+			m_ValueStack.Push(DynValue.NewTuple(f, s, var));
 		}
 
 
@@ -973,7 +998,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 			if (tbl.Type != DataType.Table)
 				throw new InternalErrorException("Unexpected type in table ctor : {0}", tbl);
 
-			tbl.Table[key] = val.ToScalar();
+			tbl.Table.Set(key, val.ToScalar());
 		}
 
 		private int ExecIndexSet(Instruction i, int instructionPtr)
@@ -992,9 +1017,9 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 				if (obj.Type == DataType.Table)
 				{
-					if (!obj.Table[idx].IsNil())
+					if (!obj.Table.Get(idx).IsNil())
 					{
-						obj.Table[idx] = value;
+						obj.Table.Set(idx, value);
 						return instructionPtr;
 					}
 
@@ -1002,7 +1027,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 					if (h == null || h.IsNil())
 					{
-						obj.Table[idx] = value;
+						obj.Table.Set(idx, value);
 						return instructionPtr;
 					}
 				}
@@ -1057,7 +1082,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 				if (obj.Type == DataType.Table)
 				{
-					var v = obj.Table[idx];
+					var v = obj.Table.Get(idx);
 
 					if (!v.IsNil())
 					{

+ 2 - 2
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_Scope.cs

@@ -56,7 +56,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 			if (dynValue.Type != DataType.Table)
 				throw new InvalidOperationException(string.Format("_ENV is not a table but a {0}", dynValue.Type));
 
-			return dynValue.Table[name];
+			return dynValue.Table.Get(name);
 		}
 
 		private void SetGlobalSymbol(DynValue dynValue, string name, DynValue value)
@@ -64,7 +64,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 			if (dynValue.Type != DataType.Table)
 				throw new InvalidOperationException(string.Format("_ENV is not a table but a {0}", dynValue.Type));
 
-			dynValue.Table[name] = value ?? DynValue.Nil;
+			dynValue.Table.Set(name, value ?? DynValue.Nil);
 		}
 
 

+ 6 - 0
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.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
 {
@@ -140,5 +141,10 @@ namespace MoonSharp.Interpreter.Execution.VM
 			return values;
 		}
 
+
+		private DynValue GetIEnumerableIteratorHelper(DynValue f)
+		{
+			return DynValue.Nil;
+		}
 	}
 }

+ 309 - 0
src/MoonSharp.Interpreter/Interop/ConversionHelper.cs

@@ -0,0 +1,309 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using MoonSharp.Interpreter.Execution;
+
+namespace MoonSharp.Interpreter.Interop
+{
+	internal static class ConversionHelper
+	{
+		static readonly Type[] NumericTypes = 
+		{
+			typeof(sbyte), 
+			typeof(byte), 
+			typeof(short), 
+			typeof(ushort), 
+			typeof(int), 
+			typeof(uint), 
+			typeof(long), 
+			typeof(ulong), 
+			typeof(float), 
+			typeof(decimal), 
+			typeof(double)
+		};
+
+		internal static bool CheckCallbackSignature(MethodInfo mi)
+		{
+			ParameterInfo[] pi = mi.GetParameters();
+
+			return (pi.Length == 2 && pi[0].ParameterType == typeof(ScriptExecutionContext)
+				&& pi[1].ParameterType == typeof(CallbackArguments) && mi.ReturnType == typeof(DynValue));
+		}
+
+		internal static DynValue TryClrObjectToSimpleMoonSharpValue(Script script, object obj)
+		{
+			if (obj == null)
+				return DynValue.Nil;
+
+			if (obj is DynValue)
+				return (DynValue)obj;
+
+			Type t = obj.GetType();
+
+			if (NumericTypes.Contains(t))
+				return DynValue.NewNumber(TypeToDouble(t, obj));
+
+			if (obj is bool)
+				return DynValue.NewBoolean((bool)obj);
+
+			if (obj is string || obj is StringBuilder || obj is char)
+				return DynValue.NewString(obj.ToString());
+
+			if (obj is Table)
+				return DynValue.NewTable((Table)obj);
+
+			if (obj is CallbackFunction)
+				return DynValue.NewCallback((CallbackFunction)obj);
+
+			if (obj is Delegate)
+			{
+				Delegate d = (Delegate)obj;
+				MethodInfo mi = d.Method;
+
+				if (CheckCallbackSignature(mi))
+					return DynValue.NewCallback((Func<ScriptExecutionContext, CallbackArguments, DynValue>)d);
+			}
+
+			return null;
+		}
+
+
+		internal static DynValue ClrObjectToComplexMoonSharpValue(Script script, object obj)
+		{
+			DynValue v = TryClrObjectToSimpleMoonSharpValue(script, obj);
+
+			if (v != null) return v;
+
+			v = script.UserDataRepository.CreateUserData(obj);
+
+			if (v != null) return v;
+
+			if (obj is Type)
+			{
+				v = script.UserDataRepository.CreateStaticUserData(obj as Type);
+			}
+
+			if (obj is System.Collections.IEnumerable)
+			{
+				var enumer = (System.Collections.IEnumerable)obj;
+				return EnumerableIterator.ConvertIterator(script, enumer.GetEnumerator());
+			}
+
+			if (obj is System.Collections.IEnumerator)
+			{
+				var enumer = (System.Collections.IEnumerator)obj;
+				return EnumerableIterator.ConvertIterator(script, enumer);
+			}
+
+			throw ScriptRuntimeException.ConvertObjectFailed(obj);
+		}
+
+		internal static object MoonSharpValueToClrObject(DynValue value)
+		{
+			switch (value.Type)
+			{
+				case DataType.Nil:
+					return null;
+				case DataType.Boolean:
+					return value.Boolean;
+				case DataType.Number:
+					return value.Number;
+				case DataType.String:
+					return value.String;
+				case DataType.Function:
+					return value.Function;
+				case DataType.Table:
+					return value.Table;
+				case DataType.Tuple:
+					return value.Tuple;
+				case DataType.UserData:
+					return value.UserData.Object;
+				case DataType.ClrFunction:
+					return value.Callback;
+				default:
+					throw ScriptRuntimeException.ConvertObjectFailed(value.Type);
+			}
+		}
+
+		internal static object MoonSharpValueToObjectOfType(DynValue value, Type t, object defaultValue)
+		{
+			if (t == typeof(DynValue))
+				return value;
+
+			if (t == typeof(object))
+				return value.ToObject();
+
+			bool isString = false;
+			bool isStringBuilder = false;
+			bool isChar = false;
+
+			if (t == typeof(string))
+				isString = true;
+			else if (t == typeof(StringBuilder))
+				isStringBuilder = true;
+			else if (t == typeof(char) && value.String.Length > 0)
+				isChar = true;
+
+			bool isAnyString = isString || isStringBuilder || isChar;
+			string str = null;
+
+			switch (value.Type)
+			{
+				case DataType.Nil:
+					if (t.IsValueType)
+					{
+						Type nt = Nullable.GetUnderlyingType(t);
+						
+						if (nt != null)
+							return null;
+
+						if (defaultValue != null)
+							return defaultValue;
+					}
+					else
+					{
+						return null;
+					}
+					break;
+				case DataType.Boolean:
+					if (t == typeof(bool))
+						return value.Boolean;
+					if (isAnyString)
+						str = value.Boolean.ToString();
+					break;
+				case DataType.Number:
+					if (NumericTypes.Contains(t))
+						return DoubleToType(t, value.Number);
+					if (isAnyString)
+						str = value.Number.ToString();
+					break;
+				case DataType.String:
+					if (isAnyString)
+						str = value.String;
+					break;
+				case DataType.Function:
+					if (t == typeof(Closure)) return value.Function;
+					break;
+				case DataType.ClrFunction:
+					if (t == typeof(CallbackFunction)) return value.Callback;
+					break;
+				case DataType.UserData:
+					if (value.UserData.Object != null)
+					{
+						if (t.IsInstanceOfType(value.UserData.Object))
+							return value.UserData.Object;
+						if (isAnyString)
+							str = value.UserData.Object.ToString();
+					}
+					break;
+				case DataType.Table:
+					if (t == typeof(Table) || t.IsAssignableFrom(typeof(Table)))
+						return value.Table;
+					else
+					{
+						object o = ConvertTableToType(value.Table, t);
+						if (o != null)
+							return o;
+					}
+					break;
+				case DataType.Tuple:
+					break;
+			}
+
+			if (str != null)
+			{
+				if (isString)
+					return str;
+				if (isStringBuilder)
+					return new StringBuilder(str);
+				if (isChar && str.Length > 0)
+					return str[0];
+			}
+
+			throw ScriptRuntimeException.ConvertObjectFailed(value.Type, t);
+		}
+
+		private static object ConvertTableToType(Table table, Type t)
+		{
+			if (t.IsAssignableFrom(typeof(Dictionary<DynValue, DynValue>)))
+				return TableToDictionary<DynValue, DynValue>(table, v => v, v => v);
+			else if (t.IsAssignableFrom(typeof(Dictionary<object, object>)))
+				return TableToDictionary<object, object>(table, v => v.ToObject(), v => v.ToObject());
+			else if (t.IsAssignableFrom(typeof(List<DynValue>)))
+				return TableToList<DynValue>(table, v => v);
+			else if (t.IsAssignableFrom(typeof(List<object>)))
+				return TableToList<object>(table, v => v.ToObject());
+			else if (t.IsAssignableFrom(typeof(DynValue[])))
+				return TableToList<DynValue>(table, v => v).ToArray();
+			else if (t.IsAssignableFrom(typeof(object[])))
+				return TableToList<object>(table, v => v.ToObject()).ToArray();
+
+			return null;
+		}
+
+		private static List<T> TableToList<T>(Table table, Func<DynValue, T> converter)
+		{
+			List<T> lst = new List<T>();
+
+			for (int i = 1, l = table.Length; i <= l; i++)
+			{
+				DynValue v = table.Get(i);
+				T o = converter(v);
+				lst.Add(o);
+			}
+
+			return lst;
+		}
+
+		private static Dictionary<TK, TV> TableToDictionary<TK, TV>(Table table, Func<DynValue, TK> keyconverter, Func<DynValue, TV> valconverter)
+		{
+			Dictionary<TK, TV> dict = new Dictionary<TK, TV>();
+
+			foreach (var kvp in table.EnumerateKeyValuePairs())
+			{
+				TK key = keyconverter(kvp.Key);
+				TV val = valconverter(kvp.Value);
+
+				dict.Add(key, val);
+			}
+
+			return dict;
+		}
+
+		internal static object DoubleToType(Type type, double d)
+		{
+			type = Nullable.GetUnderlyingType(type) ?? type;
+
+			if (type == typeof(double)) return d;
+			if (type == typeof(sbyte)) return (sbyte)d;
+			if (type == typeof(byte)) return (byte)d;
+			if (type == typeof(short)) return (short)d;
+			if (type == typeof(ushort)) return (ushort)d;
+			if (type == typeof(int)) return (int)d;
+			if (type == typeof(uint)) return (uint)d;
+			if (type == typeof(long)) return (long)d;
+			if (type == typeof(ulong)) return (ulong)d;
+			if (type == typeof(float)) return (float)d;
+			if (type == typeof(decimal)) return (decimal)d;
+			return d;
+		}
+
+		internal static double TypeToDouble(Type type, object d)
+		{
+			if (type == typeof(double)) return (double)d;
+			if (type == typeof(sbyte)) return (double)(sbyte)d;
+			if (type == typeof(byte)) return (double)(byte)d;
+			if (type == typeof(short)) return (double)(short)d;
+			if (type == typeof(ushort)) return (double)(ushort)d;
+			if (type == typeof(int)) return (double)(int)d;
+			if (type == typeof(uint)) return (double)(uint)d;
+			if (type == typeof(long)) return (double)(long)d;
+			if (type == typeof(ulong)) return (double)(ulong)d;
+			if (type == typeof(float)) return (double)(float)d;
+			if (type == typeof(decimal)) return (double)(decimal)d;
+			return (double)d;
+		}
+	}
+}

+ 0 - 161
src/MoonSharp.Interpreter/Interop/Converter.cs

@@ -1,161 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using MoonSharp.Interpreter.Execution;
-
-namespace MoonSharp.Interpreter.Interop
-{
-	public static class Converter
-	{
-		static readonly Type[] NumericTypes = 
-		{
-			typeof(sbyte), 
-			typeof(byte), 
-			typeof(short), 
-			typeof(ushort), 
-			typeof(int), 
-			typeof(uint), 
-			typeof(long), 
-			typeof(ulong), 
-			typeof(float), 
-			typeof(decimal), 
-			typeof(double)
-		}; 
-
-		public static bool CheckCallbackSignature(MethodInfo mi)
-		{
-			ParameterInfo[] pi = mi.GetParameters();
-
-			return (pi.Length == 2 && pi[0].ParameterType == typeof(ScriptExecutionContext)
-				&& pi[1].ParameterType == typeof(CallbackArguments) && mi.ReturnType == typeof(DynValue));
-		}
-
-		public static DynValue TryClrObjectToSimpleMoonSharpValue(this Script script, object obj)
-		{
-			if (obj == null)
-				return DynValue.Nil;
-
-			Type t = obj.GetType();
-
-			if (NumericTypes.Contains(t))
-				return DynValue.NewNumber(TypeToDouble(t, obj));
-
-			if (obj is bool)
-				return DynValue.NewBoolean((bool)obj);
-
-			if (obj is string || obj is StringBuilder || obj is char)
-				return DynValue.NewString(obj.ToString());
-
-			if (obj is Table)
-				return DynValue.NewTable((Table)obj);
-
-			if (obj is CallbackFunction)
-				return DynValue.NewCallback((CallbackFunction)obj);
-
-			if (obj is Delegate)
-			{
-				Delegate d = (Delegate)obj;
-				MethodInfo mi = d.Method;
-
-				if (CheckCallbackSignature(mi))
-					return DynValue.NewCallback((Func<ScriptExecutionContext, CallbackArguments, DynValue>)d);
-			}
-
-			return null;
-		}
-
-
-		public static DynValue ClrObjectToComplexMoonSharpValue(this Script script, object obj)
-		{
-			DynValue v = TryClrObjectToSimpleMoonSharpValue(script, obj);
-
-			if (v != null) return v;
-
-			v = script.UserDataRepository.CreateUserData(obj);
-
-			if (v != null) return v;
-
-			if (obj is Type)
-			{
-				v = script.UserDataRepository.CreateStaticUserData(obj as Type);
-			}
-
-			if (obj is System.Collections.IEnumerable)
-			{
-				var enumer = (System.Collections.IEnumerable)obj;
-				return EnumerableIterator.ConvertIterator(script, enumer.GetEnumerator());
-			}
-
-			if (obj is System.Collections.IEnumerator)
-			{
-				var enumer = (System.Collections.IEnumerator)obj;
-				return EnumerableIterator.ConvertIterator(script, enumer);
-			}
-
-			throw ScriptRuntimeException.ConvertObjectFailed(obj);
-		}
-
-		internal static object MoonSharpValueToClrObject(DynValue value)
-		{
-			switch (value.Type)
-			{
-				case DataType.Nil:
-					return null;
-				case DataType.Boolean:
-					return value.Boolean;
-				case DataType.Number:
-					return value.Number;
-				case DataType.String:
-					return value.String;
-				case DataType.Function:
-					return value.Function;
-				case DataType.Table:
-					return value.Table;
-				case DataType.Tuple:
-					return value.Tuple;
-				case DataType.UserData:
-					return value.UserData.Object;
-				case DataType.ClrFunction:
-					return value.Callback;
-				default:
-					throw ScriptRuntimeException.ConvertObjectFailed(value.Type);
-			}
-		}
-
-		public static object DoubleToType(Type type, double d)
-		{
-			type = Nullable.GetUnderlyingType(type) ?? type;
-
-			if (type == typeof(double)) return d;
-			if (type == typeof(sbyte)) return (sbyte)d;
-			if (type == typeof(byte)) return (byte)d;
-			if (type == typeof(short)) return (short)d;
-			if (type == typeof(ushort)) return (ushort)d;
-			if (type == typeof(int)) return (int)d;
-			if (type == typeof(uint)) return (uint)d;
-			if (type == typeof(long)) return (long)d;
-			if (type == typeof(ulong)) return (ulong)d;
-			if (type == typeof(float)) return (float)d;
-			if (type == typeof(decimal)) return (decimal)d;
-			return d;
-		}
-
-		public static double TypeToDouble(Type type, object d)
-		{
-			if (type == typeof(double)) return (double)d;
-			if (type == typeof(sbyte)) return (double)(sbyte)d;
-			if (type == typeof(byte)) return (double)(byte)d;
-			if (type == typeof(short)) return (double)(short)d;
-			if (type == typeof(ushort)) return (double)(ushort)d;
-			if (type == typeof(int)) return (double)(int)d;
-			if (type == typeof(uint)) return (double)(uint)d;
-			if (type == typeof(long)) return (double)(long)d;
-			if (type == typeof(ulong)) return (double)(ulong)d;
-			if (type == typeof(float)) return (double)(float)d;
-			if (type == typeof(decimal)) return (double)(decimal)d;
-			return (double)d;
-		}
-	}
-}

+ 1 - 1
src/MoonSharp.Interpreter/Interop/EnumerableIterator.cs

@@ -26,7 +26,7 @@ namespace MoonSharp.Interpreter.Interop
 
 			while (m_Enumerator.MoveNext())
 			{
-				DynValue v = Converter.ClrObjectToComplexMoonSharpValue(m_Script, m_Enumerator.Current);
+				DynValue v = ConversionHelper.ClrObjectToComplexMoonSharpValue(m_Script, m_Enumerator.Current);
 
 				if (!v.IsNil())
 					return v;

+ 2 - 2
src/MoonSharp.Interpreter/Interop/UserDataDescriptor.cs

@@ -55,7 +55,7 @@ namespace MoonSharp.Interpreter.Interop
 			if (m_Properties.ContainsKey(idxname))
 			{
 				object o = m_Properties[idxname].GetValue(obj);
-				return Converter.ClrObjectToComplexMoonSharpValue(this.Repository.OwnerScript, o);
+				return ConversionHelper.ClrObjectToComplexMoonSharpValue(this.Repository.OwnerScript, o);
 			}
 
 			throw ScriptRuntimeException.UserDataMissingField(this.Name, idxname);
@@ -65,7 +65,7 @@ namespace MoonSharp.Interpreter.Interop
 		{
 			if (m_Properties.ContainsKey(idxname))
 			{
-				object o = Converter.MoonSharpValueToClrObject(value);
+				object o = ConversionHelper.MoonSharpValueToClrObject(value);
 				m_Properties[idxname].SetValue(obj, o, value.Type);
 			}
 			else

+ 20 - 1
src/MoonSharp.Interpreter/Interop/UserDataMethodDescriptor.cs

@@ -14,18 +14,37 @@ namespace MoonSharp.Interpreter.Interop
 		public bool IsStatic { get; private set; }
 		public string Name { get; private set; }
 
+		private Type[] m_Arguments;
+		private object[] m_Defaults;
+
 		internal UserDataMethodDescriptor(MethodInfo mi, UserDataDescriptor userDataDescriptor)
 		{
 			this.MethodInfo = mi;
 			this.UserDataDescriptor = userDataDescriptor;
 			this.Name = mi.Name;
 			this.IsStatic = mi.IsStatic;
+
+			m_Arguments = mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
+			m_Defaults = mi.GetParameters().Select(pi => pi.DefaultValue).ToArray();
 		}
 
 
 		internal Func<ScriptExecutionContext, CallbackArguments, DynValue> GetCallback(object obj)
 		{
-			throw new NotImplementedException();
+			return (c, a) => ReflectionCallback(obj, c, a);
+		}
+
+		DynValue ReflectionCallback(object obj, ScriptExecutionContext context, CallbackArguments args)
+		{
+			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);
 		}
 	}
 }

+ 2 - 1
src/MoonSharp.Interpreter/Interop/UserDataOptimizationMode.cs

@@ -11,6 +11,7 @@ namespace MoonSharp.Interpreter.Interop
 		None,
 		Lazy,
 		Precomputed,
-		HideMembers
+		HideMembers,
+		Default
 	}
 }

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

@@ -101,7 +101,7 @@ namespace MoonSharp.Interpreter.Interop
 			try
 			{
 				if (value is double)
-					value = Converter.DoubleToType(PropertyInfo.PropertyType, (double)value);
+					value = ConversionHelper.DoubleToType(PropertyInfo.PropertyType, (double)value);
 
 				if (UserDataDescriptor.OptimizationMode == UserDataOptimizationMode.Lazy && m_OptimizedSetter == null)
 					OptimizeSetter();

+ 13 - 13
src/MoonSharp.Interpreter/Modules/ModuleRegister.cs

@@ -31,11 +31,11 @@ namespace MoonSharp.Interpreter
 
 		public static Table RegisterConstants(this Table table)
 		{
-			table["_G"] = DynValue.NewTable(table);
-			table["_VERSION"] = DynValue.NewString(string.Format("Moon# {0}", 
+			table.Set("_G", DynValue.NewTable(table));
+			table.Set("_VERSION", DynValue.NewString(string.Format("Moon# {0}", 
 				Assembly.GetExecutingAssembly().GetName().Version.Major,
-				Assembly.GetExecutingAssembly().GetName().Version.Minor));
-			table["_MOONSHARP"] = DynValue.NewString(Assembly.GetExecutingAssembly().GetName().Version.ToString());
+				Assembly.GetExecutingAssembly().GetName().Version.Minor)));
+			table.Set("_MOONSHARP", DynValue.NewString(Assembly.GetExecutingAssembly().GetName().Version.ToString()));
 
 			return table;
 		}
@@ -52,14 +52,14 @@ namespace MoonSharp.Interpreter
 				{
 					MoonSharpMethodAttribute attr = (MoonSharpMethodAttribute)mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).First();
 
-					if (!Converter.CheckCallbackSignature(mi))
+					if (!ConversionHelper.CheckCallbackSignature(mi))
 							throw new ArgumentException(string.Format("Method {0} does not have the right signature.", mi.Name));
 
 					Func<ScriptExecutionContext, CallbackArguments, DynValue> func = (Func<ScriptExecutionContext, CallbackArguments, DynValue>)Delegate.CreateDelegate(typeof(Func<ScriptExecutionContext, CallbackArguments, DynValue>), mi);
 
 					string name = (!string.IsNullOrEmpty(attr.Name)) ? attr.Name : mi.Name;
 
-					table[name] = DynValue.NewCallback(func);
+					table.Set(name, DynValue.NewCallback(func));
 				}
 				else if (mi.Name == "MoonSharpInit")
 				{
@@ -91,12 +91,12 @@ namespace MoonSharp.Interpreter
 			if (fi.FieldType == typeof(string))
 			{
 				string val = fi.GetValue(o) as string;
-				table[name] = DynValue.NewString(val);
+				table.Set(name, DynValue.NewString(val));
 			}
 			else if (fi.FieldType == typeof(double))
 			{
 				double val = (double)fi.GetValue(o);
-				table[name] = DynValue.NewNumber(val);
+				table.Set(name, DynValue.NewNumber(val));
 			}
 			else
 			{
@@ -115,7 +115,7 @@ namespace MoonSharp.Interpreter
 
 			DynValue fn = table.OwnerScript.LoadFunction(val, table, name);
 
-			table[name] = fn;
+			table.Set(name, fn);
 		}
 
 
@@ -130,13 +130,13 @@ namespace MoonSharp.Interpreter
 			else
 			{
 				Table table = new Table(gtable.OwnerScript);
-				gtable[attr.Namespace] = DynValue.NewTable(table);
+				gtable.Set(attr.Namespace, DynValue.NewTable(table));
 
 				DynValue package = gtable.RawGet("package");
 
 				if (package == null || package.Type != DataType.Table)
 				{
-					gtable["package"] = package = DynValue.NewTable(gtable.OwnerScript);
+					gtable.Set("package", package = DynValue.NewTable(gtable.OwnerScript));
 				}
 
 
@@ -144,10 +144,10 @@ namespace MoonSharp.Interpreter
 
 				if (loaded == null || loaded.Type != DataType.Table)
 				{
-					package.Table["loaded"] = loaded = DynValue.NewTable(gtable.OwnerScript);
+					package.Table.Set("loaded", loaded = DynValue.NewTable(gtable.OwnerScript));
 				}
 
-				loaded.Table[attr.Namespace] = DynValue.NewTable(table);
+				loaded.Table.Set(attr.Namespace, DynValue.NewTable(table));
 
 				return table;
 			}

+ 1 - 1
src/MoonSharp.Interpreter/MoonSharp.Interpreter.csproj

@@ -132,7 +132,7 @@
     <Compile Include="Execution\VM\Chunk.cs" />
     <Compile Include="Execution\VM\Processor\Processor_Errors.cs" />
     <Compile Include="Interface\IteratorHelper.cs" />
-    <Compile Include="Interop\Converter.cs" />
+    <Compile Include="Interop\ConversionHelper.cs" />
     <Compile Include="Interop\EnumerableIterator.cs">
       <SubType>Code</SubType>
     </Compile>

+ 2 - 2
src/MoonSharp/Program.cs

@@ -40,7 +40,7 @@ namespace MoonSharp
 			{
 				Script script = new Script();
 
-				script.Globals["print"] = DynValue.NewCallback(new CallbackFunction(Print));
+				script.Globals.Set("print", DynValue.NewCallback(new CallbackFunction(Print)));
 
 				script.DoFile(args[0]);
 
@@ -55,7 +55,7 @@ namespace MoonSharp
 
 				Script script = new Script();
 
-				script.Globals["print"] = DynValue.NewCallback(new CallbackFunction(Print));
+				script.Globals.Set("print", DynValue.NewCallback(new CallbackFunction(Print)));
 
 				string cmd = "";
 

+ 2 - 2
src/PerformanceComparison/Program.cs

@@ -101,7 +101,7 @@ end
 		{
 			Script script = new Script();
 			Table t = script.Globals;
-			t["print"] = DynValue.NewCallback(Print);
+			t.Set("print", DynValue.NewCallback(Print));
 
 
 			DynValue retVal = script.DoFile("test.lua");
@@ -135,7 +135,7 @@ end
 			sw = Stopwatch.StartNew();
 
 			var script = new Script();
-			script.Globals["print"] = DynValue.NewCallback(new CallbackFunction(Print));
+			script.Globals.Set("print", DynValue.NewCallback(new CallbackFunction(Print)));
 
 			DynValue func = script.LoadString(scriptText);