Browse Source

before tuple reform

Xanathar 11 years ago
parent
commit
b27528eeeb

+ 151 - 0
src/MoonSharp.Interpreter.Tests/EndToEnd/MetatableTests.cs

@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MoonSharp.Interpreter.CoreLib;
+using MoonSharp.Interpreter.Execution;
+using NUnit.Framework;
+
+namespace MoonSharp.Interpreter.Tests.EndToEnd
+{
+	[TestFixture]
+	public class MetatableTests
+	{
+		[Test]
+		public void TableIPairsWithMetatable()
+		{
+			string script = @"    
+				test = { 2, 4, 6 }
+
+				meta = { }
+
+				function meta.__ipairs(t)
+					local function ripairs_it(t,i)
+						i=i-1
+						local v=t[i]
+						if v==nil then return v end
+						return i,v
+					end
+
+					return ripairs_it, t, #t+1
+				end
+
+				setmetatable(test, meta);
+
+				x = '';
+
+				for i,v in ipairs(test) do
+					x = x .. i;
+				end
+
+				return x;";
+
+			Table globalCtx = new Table();
+
+			globalCtx.RegisterModuleType<TableIterators>();
+			globalCtx.RegisterModuleType<MetaTableMethods>();
+
+			RValue res = MoonSharpInterpreter.LoadFromString(script).Execute(globalCtx);
+
+			Assert.AreEqual(DataType.String, res.Type);
+			Assert.AreEqual("321", res.String);
+		}
+
+		[Test]
+		public void TableAddWithMetatable()
+		{
+			string script = @"    
+				v1 = { 'aaaa' }
+				v2 = { 'aaaaaa' } 
+
+				meta = { }
+
+				function meta.__add(t1, t2)
+					local o1 = #t1[1];
+					local o2 = #t2[1];
+	
+					return o1 * o2;
+				end
+
+
+				setmetatable(v1, meta);
+
+
+				return(v1 + v2);";
+
+			Table globalCtx = new Table();
+
+			globalCtx.RegisterModuleType<TableIterators>();
+			globalCtx.RegisterModuleType<MetaTableMethods>();
+
+			RValue res = MoonSharpInterpreter.LoadFromString(script).Execute(globalCtx);
+
+			Assert.AreEqual(DataType.Number, res.Type);
+			Assert.AreEqual(24, res.Number);
+		}
+
+		[Test]
+		public void MetatableEquality()
+		{
+			string script = @"    
+				t1a = {}
+				t1b = {}
+				t2  = {}
+				mt1 = { __eq = function( o1, o2 ) return 'whee' end }
+				mt2 = { __eq = function( o1, o2 ) return 'whee' end }
+
+				setmetatable( t1a, mt1 )
+				setmetatable( t1b, mt1 )
+				setmetatable( t2,  mt2 )
+
+				return ( t1a == t1b ), ( t1a == t2 ) 
+				";
+
+			Table globalCtx = new Table();
+
+			globalCtx.RegisterModuleType<TableIterators>();
+			globalCtx.RegisterModuleType<MetaTableMethods>();
+
+			RValue res = MoonSharpInterpreter.LoadFromString(script).Execute(globalCtx);
+
+			Assert.AreEqual(DataType.Tuple, res.Type);
+			Assert.AreEqual(true, res.Tuple[0].Boolean);
+			Assert.AreEqual(false, res.Tuple[1].Boolean);
+
+		}
+
+
+		[Test]
+		public void MetatableCall()
+		{
+			string script = @"    
+					t = { }
+					meta = { }
+
+					x = 0;
+
+					function meta.__call(f, y)
+						x = 156 * y;
+					end
+
+					setmetatable(t, meta);
+
+					t(3);
+					return x;
+				";
+
+			Table globalCtx = new Table();
+
+			globalCtx.RegisterModuleType<TableIterators>();
+			globalCtx.RegisterModuleType<MetaTableMethods>();
+
+			RValue res = MoonSharpInterpreter.LoadFromString(script).Execute(globalCtx);
+
+
+			Assert.AreEqual(DataType.Number, res.Type);
+			Assert.AreEqual(468, res.Number);
+
+		}
+
+	}
+}

+ 36 - 0
src/MoonSharp.Interpreter.Tests/EndToEnd/SimpleTests.cs

@@ -704,6 +704,42 @@ namespace MoonSharp.Interpreter.Tests
 
 
 		}
 		}
 
 
+		[Test]
+		public void ExpressionReducesTuples()
+		{
+			string script = @"
+					function x()
+						return 1,2
+					end
+
+					do return (x()); end
+					do return x(); end
+								";
+
+			RValue res = MoonSharpInterpreter.LoadFromString(script).Execute(null);
+
+			Assert.AreEqual(DataType.Number, res);
+			Assert.AreEqual(1, res.Number);
+		}
+
+		[Test]
+		public void ExpressionReducesTuples2()
+		{
+			string script = @"
+					function x()
+						return 3,4
+					end
+
+					return 1,x(),x()
+								";
+
+			RValue res = MoonSharpInterpreter.LoadFromString(script).Execute(null);
+
+			Assert.AreEqual(DataType.Tuple, res);
+			Assert.AreEqual(4, res.Tuple.Length);
+		}
+
+
 		[Test]
 		[Test]
 		public void ArgsDoNotChange()
 		public void ArgsDoNotChange()
 		{
 		{

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

@@ -74,6 +74,9 @@
   <ItemGroup>
   <ItemGroup>
     <Compile Include="EndToEnd\ClosureTests.cs" />
     <Compile Include="EndToEnd\ClosureTests.cs" />
     <Compile Include="EndToEnd\LuaTestSuiteExtract.cs" />
     <Compile Include="EndToEnd\LuaTestSuiteExtract.cs" />
+    <Compile Include="EndToEnd\MetatableTests.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="EndToEnd\TailCallTests.cs" />
     <Compile Include="EndToEnd\TailCallTests.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="EndToEnd\SimpleTests.cs" />
     <Compile Include="EndToEnd\SimpleTests.cs" />

+ 95 - 7
src/MoonSharp.Interpreter/CoreLib/MetaTableMethods.cs

@@ -6,14 +6,102 @@ using MoonSharp.Interpreter.Execution;
 
 
 namespace MoonSharp.Interpreter.CoreLib
 namespace MoonSharp.Interpreter.CoreLib
 {
 {
-	public static class MetaTableMethods
+	[MoonSharpModule]
+	public class MetaTableMethods
 	{
 	{
-		public static RValue setmetatable(RValue[] values) { return RValue.Nil; }
-		public static RValue getmetatable(RValue[] values) { return RValue.Nil; }
-		public static RValue rawget(RValue[] values) { return RValue.Nil; }
-		public static RValue rawset(RValue[] values) { return RValue.Nil; }
-		public static RValue rawequal(RValue[] values) { return RValue.Nil; }
-		public static RValue rawlen(RValue[] values) { return RValue.Nil; }
+		// setmetatable (table, metatable)
+		// -------------------------------------------------------------------------------------------------------------------
+		// Sets the metatable for the given table. (You cannot change the metatable of other 
+		// types from Lua, only from C.) If metatable is nil, removes the metatable of the given table. 
+		// If the original metatable has a "__metatable" field, raises an error ("cannot change a protected metatable").
+		// This function returns table. 
+		[MoonSharpMethod]
+		public static RValue setmetatable(IExecutionContext executionContext, CallbackArguments args)  
+		{
+			RValue table = args.AsType(0, "setmetatable", DataType.Table);
+			RValue metatable = args.AsType(1, "setmetatable", DataType.Table, true);
+
+			RValue curmeta = executionContext.GetMetamethod(table, "__metatable");
+
+			if (curmeta != null)
+			{
+				throw new ScriptRuntimeException(null, "cannot change a protected metatable");
+			}
+
+			table.Meta = metatable;
+			return table;
+		}
+
+		// getmetatable (object)
+		// -------------------------------------------------------------------------------------------------------------------
+		// If object does not have a metatable, returns nil. Otherwise, if the object's metatable 
+		// has a "__metatable" field, returns the associated value. Otherwise, returns the metatable of the given object. 
+		[MoonSharpMethod]
+		public static RValue getmetatable(IExecutionContext executionContext, CallbackArguments args)  
+		{
+			RValue obj = args[0];
+
+			if (obj.Type == DataType.Nil)
+				return RValue.Nil;
+
+			RValue curmeta = executionContext.GetMetamethod(obj, "__metatable");
+
+			if (curmeta != null)
+			{
+				return curmeta;
+			}
+
+			return obj.Meta ?? RValue.Nil;
+		}
+
+		// rawget (table, index)
+		// -------------------------------------------------------------------------------------------------------------------
+		// Gets the real value of table[index], without invoking any metamethod. table must be a table; index may be any value.
+		[MoonSharpMethod]
+		public static RValue rawget(IExecutionContext executionContext, CallbackArguments args)  
+		{
+			RValue table = args.AsType(0, "rawget", DataType.Table);
+			RValue index = args[1];
+
+			return table.Table[index];
+		}
+
+		// rawset (table, index, value)
+		// -------------------------------------------------------------------------------------------------------------------
+		// Sets the real value of table[index] to value, without invoking any metamethod. table must be a table, 
+		// index any value different from nil and NaN, and value any Lua value.
+		// This function returns table. 
+		[MoonSharpMethod]
+		public static RValue rawset(IExecutionContext executionContext, CallbackArguments args)  
+		{
+			RValue table = args.AsType(0, "rawset", DataType.Table);
+			RValue index = args[1];
+
+			table.Table[index] = args[2];
+
+			return table;
+		}
+
+		// rawequal (v1, v2)
+		// -------------------------------------------------------------------------------------------------------------------
+		// Checks whether v1 is equal to v2, without invoking any metamethod. Returns a boolean. 
+		[MoonSharpMethod]
+		public static RValue rawequal(IExecutionContext executionContext, CallbackArguments args)  
+		{
+			RValue v1 = args[0];
+			RValue v2 = args[1];
+
+			return new RValue(v1.Equals(v2)); 
+		}
+
+		//rawlen (v)
+		// -------------------------------------------------------------------------------------------------------------------
+		//Returns the length of the object v, which must be a table or a string, without invoking any metamethod. Returns an integer number.	
+		[MoonSharpMethod]
+		public static RValue rawlen(IExecutionContext executionContext, CallbackArguments args) 
+		{
+			return new RValue(args[0].GetLength());
+		}
 
 
 
 
 
 

+ 12 - 6
src/MoonSharp.Interpreter/CoreLib/TableIterators.cs

@@ -10,8 +10,14 @@ namespace MoonSharp.Interpreter.CoreLib
 	[MoonSharpModule]
 	[MoonSharpModule]
 	public class TableIterators
 	public class TableIterators
 	{
 	{
+		// ipairs (t)
+		// -------------------------------------------------------------------------------------------------------------------
+		// If t has a metamethod __ipairs, calls it with t as argument and returns the first three results from the call.
+		// Otherwise, returns three values: an iterator function, the table t, and 0, so that the construction
+		//	  for i,v in ipairs(t) do body end
+		// will iterate over the pairs (1,t[1]), (2,t[2]), ..., up to the first integer key absent from the table. 
 		[MoonSharpMethod]
 		[MoonSharpMethod]
-		public static RValue ipairs(IExecutionContext executionContext, CallbackArguments args) 
+		static RValue ipairs(IExecutionContext executionContext, CallbackArguments args) 
 		{
 		{
 			RValue table = args[0];
 			RValue table = args[0];
 
 
@@ -28,7 +34,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		// will iterate over all key–value pairs of table t.
 		// will iterate over all key–value pairs of table t.
 		// See function next for the caveats of modifying the table during its traversal. 
 		// See function next for the caveats of modifying the table during its traversal. 
 		[MoonSharpMethod]
 		[MoonSharpMethod]
-		public static RValue pairs(IExecutionContext executionContext, CallbackArguments args) 
+		static RValue pairs(IExecutionContext executionContext, CallbackArguments args) 
 		{
 		{
 			RValue table = args[0];
 			RValue table = args[0];
 
 
@@ -49,7 +55,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		// The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. 
 		// The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. 
 		// You may however modify existing fields. In particular, you may clear existing fields. 
 		// You may however modify existing fields. In particular, you may clear existing fields. 
 		[MoonSharpMethod]
 		[MoonSharpMethod]
-		public static RValue next(IExecutionContext executionContext, CallbackArguments args) 
+		static RValue next(IExecutionContext executionContext, CallbackArguments args) 
 		{
 		{
 			RValue table = args.AsType(0, "next", DataType.Table);
 			RValue table = args.AsType(0, "next", DataType.Table);
 			RValue index = args[1];
 			RValue index = args[1];
@@ -62,10 +68,10 @@ namespace MoonSharp.Interpreter.CoreLib
 		// __next_i (table [, index])
 		// __next_i (table [, index])
 		// -------------------------------------------------------------------------------------------------------------------
 		// -------------------------------------------------------------------------------------------------------------------
 		// Allows a program to traverse all fields of an array. index is an integer number
 		// Allows a program to traverse all fields of an array. index is an integer number
-		private static RValue __next_i(IExecutionContext executionContext, CallbackArguments args) 
+		static RValue __next_i(IExecutionContext executionContext, CallbackArguments args) 
 		{
 		{
-			RValue table = args.AsType(0, "__next_i", DataType.Table);
-			RValue index = args.AsType(1, "__next_i", DataType.Number);
+			RValue table = args.AsType(0, "!!next_i!!", DataType.Table);
+			RValue index = args.AsType(1, "!!next_i!!", DataType.Number);
 
 
 			int idx = ((int)index.Number) + 1;
 			int idx = ((int)index.Number) + 1;
 			RValue val = table.Table[idx];
 			RValue val = table.Table[idx];

+ 3 - 1
src/MoonSharp.Interpreter/Errors/ScriptRuntimeException.cs

@@ -22,7 +22,9 @@ namespace MoonSharp.Interpreter
 				return "";
 				return "";
 
 
 			return "@ " + tree.GetText();
 			return "@ " + tree.GetText();
-
 		}
 		}
+
+
+
 	}
 	}
 }
 }

+ 4 - 1
src/MoonSharp.Interpreter/Execution/DataTypes/CallbackArguments.cs

@@ -44,8 +44,11 @@ namespace MoonSharp.Interpreter.Execution
 				argNum + 1, funcName, expected, got);
 				argNum + 1, funcName, expected, got);
 		}
 		}
 
 
-		public RValue AsType(int argNum, string funcName, DataType type)
+		public RValue AsType(int argNum, string funcName, DataType type, bool allowNil = false)
 		{
 		{
+			if (allowNil && this[argNum].Type == DataType.Nil)
+				return this[argNum];
+
 			if (this[argNum].Type != type)
 			if (this[argNum].Type != type)
 				ThrowBadArgument(argNum, funcName, type, this[argNum].Type);
 				ThrowBadArgument(argNum, funcName, type, this[argNum].Type);
 
 

+ 32 - 7
src/MoonSharp.Interpreter/Execution/DataTypes/RValue.cs

@@ -25,7 +25,7 @@ namespace MoonSharp.Interpreter.Execution
 		public bool ReadOnly { get; internal set; }
 		public bool ReadOnly { get; internal set; }
 		public LRef Symbol { get; private set; }
 		public LRef Symbol { get; private set; }
 		public CallbackFunction Callback { get; set; }
 		public CallbackFunction Callback { get; set; }
-		public RValue Meta { get; private set; }
+		public RValue Meta { get; set; }
 
 
 		private int m_HashCode = -1;
 		private int m_HashCode = -1;
 
 
@@ -158,6 +158,22 @@ namespace MoonSharp.Interpreter.Execution
 			False = new RValue(false).AsReadOnly();
 			False = new RValue(false).AsReadOnly();
 		}
 		}
 
 
+		public string AsSimpleString()
+		{
+			RValue rv = ToSimplestValue();
+			if (rv.Type == DataType.Number)
+			{
+				return rv.Number.ToString();
+			}
+			else if (rv.Type == DataType.String)
+			{
+				return rv.String;
+			}
+			return null;
+		}
+
+
+
 		public string AsString()
 		public string AsString()
 		{
 		{
 			switch (Type)
 			switch (Type)
@@ -265,6 +281,8 @@ namespace MoonSharp.Interpreter.Execution
 			if (other == null) return false;
 			if (other == null) return false;
 			if (other.Type != this.Type) return false;
 			if (other.Type != this.Type) return false;
 
 
+			if (other.Meta != this.Meta) return false;
+
 			switch (Type)
 			switch (Type)
 			{
 			{
 				case DataType.Nil:
 				case DataType.Nil:
@@ -316,20 +334,20 @@ namespace MoonSharp.Interpreter.Execution
 				return new RValue[] { this };
 				return new RValue[] { this };
 		}
 		}
 
 
-		public RValue AsNumber()
+		public double? AsNumber()
 		{
 		{
 			RValue rv = ToSimplestValue();
 			RValue rv = ToSimplestValue();
 			if (rv.Type == DataType.Number)
 			if (rv.Type == DataType.Number)
 			{
 			{
-				return rv;
+				return rv.Number;
 			}
 			}
 			else if (rv.Type == DataType.String)
 			else if (rv.Type == DataType.String)
 			{
 			{
 				double num;
 				double num;
-				if (double.TryParse(rv.String, out num))
-					return new RValue(num);
+				if (double.TryParse(rv.String, NumberStyles.Any, CultureInfo.InvariantCulture, out num))
+					return num;
 			}
 			}
-			return RValue.Nil;
+			return null;
 		}
 		}
 
 
 		public RValue AsBoolean()
 		public RValue AsBoolean()
@@ -405,8 +423,15 @@ namespace MoonSharp.Interpreter.Execution
 			throw new ScriptRuntimeException(null, "Can't get length of type {0}", this.Type);
 			throw new ScriptRuntimeException(null, "Can't get length of type {0}", this.Type);
 		}
 		}
 
 
+		public bool IsNil()
+		{
+			return this.Type == DataType.Nil;
+		}
 
 
-
+		public bool IsNilOrNan()
+		{
+			return (this.Type == DataType.Nil) || (this.Type == DataType.Number && double.IsNaN(this.Number));
+		}
 
 
 		internal void AssignNumber(double num)
 		internal void AssignNumber(double num)
 		{
 		{

+ 8 - 0
src/MoonSharp.Interpreter/Execution/DataTypes/Table.cs

@@ -55,6 +55,14 @@ namespace MoonSharp.Interpreter.Execution
 			}
 			}
 			set 
 			set 
 			{
 			{
+				if (key.IsNilOrNan())
+				{
+					if (key.IsNil())
+						throw new ScriptRuntimeException(null, "table index is nil");
+					else
+						throw new ScriptRuntimeException(null, "table index is NaN");
+				}
+
 				if (key.Type == DataType.String)
 				if (key.Type == DataType.String)
 				{
 				{
 					this[key.String] = value;
 					this[key.String] = value;

+ 6 - 1
src/MoonSharp.Interpreter/Execution/VM/Chunk.cs

@@ -110,7 +110,12 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 
 		public Instruction Operator(OpCode opcode)
 		public Instruction Operator(OpCode opcode)
 		{
 		{
-			return Emit(new Instruction() { OpCode = opcode });
+			var i = Emit(new Instruction() { OpCode = opcode });
+
+			if (opcode == OpCode.Eq || opcode == OpCode.Less || opcode == OpCode.LessEq)
+				Emit(new Instruction() { OpCode = OpCode.ToBool });
+
+			return i;
 		}
 		}
 
 
 
 

+ 1 - 0
src/MoonSharp.Interpreter/Execution/VM/OpCode.cs

@@ -60,6 +60,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 		MkTuple,	// Creates a tuple from the topmost n values
 		MkTuple,	// Creates a tuple from the topmost n values
 		Incr,		// Performs an add operation, without extracting the operands from the v-stack and assuming the operands are numbers.
 		Incr,		// Performs an add operation, without extracting the operands from the v-stack and assuming the operands are numbers.
 		ToNum,		// Converts the top of the stack to a number
 		ToNum,		// Converts the top of the stack to a number
+		ToBool,		// Converts the top of the stack to a boolean
 		ExpTuple,	// Expands a tuple on the stack
 		ExpTuple,	// Expands a tuple on the stack
 
 
 		// Tables
 		// Tables

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

@@ -24,13 +24,18 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 
 		RValue IExecutionContext.GetMetamethod(RValue value, string metamethod)
 		RValue IExecutionContext.GetMetamethod(RValue value, string metamethod)
 		{
 		{
-			if (value.Meta == null)
+			if (value.Meta == null || value.Type == DataType.Nil)
 				return null;
 				return null;
 
 
 			if (value.Meta.Type != DataType.Table)
 			if (value.Meta.Type != DataType.Table)
 				throw new InternalErrorException("Metatable is not a table!");
 				throw new InternalErrorException("Metatable is not a table!");
 
 
-			return value.Meta.Table.RawGet(metamethod);
+			var metameth = value.Meta.Table.RawGet(metamethod);
+			
+			if (metameth == null || metameth.Type == DataType.Nil)
+				return null;
+
+			return metameth;
 		}
 		}
 
 
 		RValue IExecutionContext.GetMetamethodTailCall(RValue value, string metamethod, params RValue[] args)
 		RValue IExecutionContext.GetMetamethodTailCall(RValue value, string metamethod, params RValue[] args)

+ 353 - 130
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs

@@ -37,34 +37,40 @@ namespace MoonSharp.Interpreter.Execution.VM
 						m_ValueStack.Push(i.Value);
 						m_ValueStack.Push(i.Value);
 						break;
 						break;
 					case OpCode.Add:
 					case OpCode.Add:
-						ExecAdd(i);
+						instructionPtr = ExecAdd(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Concat:
 					case OpCode.Concat:
-						ExecConcat(i);
+						instructionPtr = ExecConcat(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Neg:
 					case OpCode.Neg:
-						ExecNeg(i);
+						instructionPtr = ExecNeg(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Sub:
 					case OpCode.Sub:
-						ExecSub(i);
+						instructionPtr = ExecSub(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Mul:
 					case OpCode.Mul:
-						ExecMul(i);
+						instructionPtr = ExecMul(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Div:
 					case OpCode.Div:
-						ExecDiv(i);
+						instructionPtr = ExecDiv(i, instructionPtr);
+						break;
+					case OpCode.Mod:
+						instructionPtr = ExecMod(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Power:
 					case OpCode.Power:
-						ExecPower(i);
+						instructionPtr = ExecPower(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Eq:
 					case OpCode.Eq:
-						ExecEq(i);
+						instructionPtr = ExecEq(i, instructionPtr);
 						break;
 						break;
 					case OpCode.LessEq:
 					case OpCode.LessEq:
-						ExecLessEq(i);
+						instructionPtr = ExecLessEq(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Less:
 					case OpCode.Less:
-						ExecLess(i);
+						instructionPtr = ExecLess(i, instructionPtr);
+						break;
+					case OpCode.Len:
+						instructionPtr = ExecLen(i, instructionPtr);
 						break;
 						break;
 					case OpCode.Call:
 					case OpCode.Call:
 						instructionPtr = Internal_ExecCall(i.NumVal, instructionPtr);
 						instructionPtr = Internal_ExecCall(i.NumVal, instructionPtr);
@@ -103,7 +109,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 						instructionPtr = i.NumVal;
 						instructionPtr = i.NumVal;
 						break;
 						break;
 					case OpCode.MkTuple:
 					case OpCode.MkTuple:
-						m_ValueStack.Push(RValue.FromPotentiallyNestedTuple(StackTopToArrayReverse(i.NumVal, true)));
+						ExecMkTuple(i);
 						break;
 						break;
 					case OpCode.Enter:
 					case OpCode.Enter:
 						NilifyBlockData(i.Block);
 						NilifyBlockData(i.Block);
@@ -118,6 +124,9 @@ namespace MoonSharp.Interpreter.Execution.VM
 					case OpCode.BeginFn:
 					case OpCode.BeginFn:
 						ExecBeginFn(i);
 						ExecBeginFn(i);
 						break;
 						break;
+					case OpCode.ToBool:
+						m_ValueStack.Push(m_ValueStack.Pop().AsBoolean());
+						break;
 					case OpCode.Args:
 					case OpCode.Args:
 						ExecArgs(i);
 						ExecArgs(i);
 						break;
 						break;
@@ -130,7 +139,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 						ExecIncr(i);
 						ExecIncr(i);
 						break;
 						break;
 					case OpCode.ToNum:
 					case OpCode.ToNum:
-						m_ValueStack.Push(m_ValueStack.Pop().AsNumber());
+						ExecToNum(i);
 						break;
 						break;
 					case OpCode.SymStorN:
 					case OpCode.SymStorN:
 						ExecSymStorN(i);
 						ExecSymStorN(i);
@@ -153,9 +162,6 @@ namespace MoonSharp.Interpreter.Execution.VM
 					case OpCode.NewTable:
 					case OpCode.NewTable:
 						m_ValueStack.Push(new RValue(new Table()));
 						m_ValueStack.Push(new RValue(new Table()));
 						break;
 						break;
-					case OpCode.Len:
-						ExecLen(i);
-						break;
 					case OpCode.IterPrep:
 					case OpCode.IterPrep:
 						ExecIterPrep(i);
 						ExecIterPrep(i);
 						break;
 						break;
@@ -183,8 +189,35 @@ namespace MoonSharp.Interpreter.Execution.VM
 
 
 		}
 		}
 
 
+		private void ExecMkTuple(Instruction i)
+		{
+			//RValue[] t = new RValue[i.NumVal];
+			//for(int ii = i.NumVal - 1; ii >= 0; ii--)
+			//{
+			//	if (ii == i.NumVal - 1)
+			//	{
+			//		t[ii] = m_ValueStack.Pop();
+			//	}
+			//	else
+			//	{
+			//		t[ii] = m_ValueStack.Pop().ToSimplestValue();
+			//	}
+			//}
+
 
 
+			var explist = StackTopToArrayReverse(i.NumVal, true);
+			var v = RValue.FromPotentiallyNestedTuple(explist);
+			m_ValueStack.Push(v);
+		}
 
 
+		private void ExecToNum(Instruction i)
+		{
+			double? v = m_ValueStack.Pop().AsNumber();
+			if (v.HasValue)
+				m_ValueStack.Push(new RValue(v.Value));
+			else
+				throw new ScriptRuntimeException(null, "Can't convert value to number");
+		}
 
 
 
 
 		private void ExecIterUpd(Instruction i)
 		private void ExecIterUpd(Instruction i)
@@ -348,6 +381,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 			}
 			}
 		}
 		}
 
 
+
 		private int Internal_ExecCall(int argsCount, int instructionPtr)
 		private int Internal_ExecCall(int argsCount, int instructionPtr)
 		{
 		{
 			RValue fn = m_ValueStack.Peek(argsCount);
 			RValue fn = m_ValueStack.Peek(argsCount);
@@ -374,7 +408,26 @@ namespace MoonSharp.Interpreter.Execution.VM
 			}
 			}
 			else
 			else
 			{
 			{
-				throw new NotImplementedException("Meta");
+				if (fn.Meta != null)
+				{
+					var m = fn.Meta.Table.RawGet("__call");
+
+					if (m != null && m.Type != DataType.Nil)
+					{
+						RValue[] tmp = new RValue[argsCount + 1];
+						for (int i = 0; i < argsCount + 1; i++)
+							tmp[i] = m_ValueStack.Pop();
+
+						m_ValueStack.Push(m);
+
+						for (int i = argsCount; i >= 0; i--)
+							m_ValueStack.Push(tmp[i]);
+
+						return Internal_ExecCall(argsCount + 1, instructionPtr);
+					}
+				}
+
+				throw new NotImplementedException("Can't call non function");
 			}
 			}
 		}
 		}
 
 
@@ -440,239 +493,409 @@ namespace MoonSharp.Interpreter.Execution.VM
 			}
 			}
 		}
 		}
 
 
-
-		private void ExecLen(Instruction i)
+		private void Internal_Assign(LRef l, RValue r)
 		{
 		{
-			RValue r = m_ValueStack.Pop();
+			if (l.i_Type == LRefType.Index)
+			{
+				l.i_TableRefObject.Table[l.i_TableRefIndex] = r;
+			}
+			else
+			{
+				this.AssignGenericSymbol(l, r.ToSimplestValue());
+			}
+		}
 
 
-			if (r.Type == DataType.Table)
-				m_ValueStack.Push(new RValue(r.Table.Length));
-			else if (r.Type == DataType.String)
-				m_ValueStack.Push(new RValue(r.String.Length));
+		private void Internal_Assign(RValue l, RValue r)
+		{
+			if (l.Type == DataType.Symbol)
+			{
+				Internal_Assign(l.Symbol, r);
+			}
 			else
 			else
-				throw new NotImplementedException("Meta operators");
+			{
+				throw new NotImplementedException("How should we manage this ?");
+			}
 		}
 		}
 
 
-		private void ExecAdd(Instruction i)
+		private void ExecIndexGet(Instruction i, bool methodCall)
 		{
 		{
-			RValue r = m_ValueStack.Pop();
-			RValue l = m_ValueStack.Pop();
+			RValue indexValue = m_ValueStack.Pop();
+			RValue baseValue = m_ValueStack.Pop();
 
 
-			if (r.Type == DataType.Number && l.Type == DataType.Number)
-				m_ValueStack.Push(new RValue(l.Number + r.Number));
+			if (baseValue.Type != DataType.Table)
+			{
+				throw new NotImplementedException("META! : Can't index non-table yet");
+			}
 			else
 			else
-				throw new NotImplementedException("Meta operators");
+			{
+				RValue v = baseValue.Table[indexValue];
+				m_ValueStack.Push(v.AsReadOnly());
+			}
+
+			if (methodCall)
+				m_ValueStack.Push(baseValue);
 		}
 		}
 
 
-		private void ExecConcat(Instruction i)
+		private void ExecIndexRef(Instruction i, bool keepOnStack)
 		{
 		{
-			RValue r = m_ValueStack.Pop();
-			RValue l = m_ValueStack.Pop();
+			RValue indexValue = m_ValueStack.Pop();
+			RValue baseValue = keepOnStack ? m_ValueStack.Peek() : m_ValueStack.Pop();
 
 
-			if ((r.Type == DataType.String || r.Type == DataType.Number) && (l.Type == DataType.String || l.Type == DataType.Number))
-				m_ValueStack.Push(new RValue(l.AsString() + r.AsString()));
+			if (baseValue.Type != DataType.Table)
+			{
+				throw new NotImplementedException("META! : Can't index non-table yet");
+			}
 			else
 			else
-				throw new NotImplementedException("Meta operators");
+			{
+				LRef s = LRef.ObjIndex(baseValue, indexValue);
+				m_ValueStack.Push(new RValue(s));
+			}
 		}
 		}
 
 
-		private void ExecSub(Instruction i)
+		private void ExecStore(Instruction i)
 		{
 		{
 			RValue r = m_ValueStack.Pop();
 			RValue r = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 
 
-			if (r.Type == DataType.Number && l.Type == DataType.Number)
-				m_ValueStack.Push(new RValue(l.Number - r.Number));
-			else
-				throw new NotImplementedException("Meta operators");
+			Internal_Assign(l, r);
 		}
 		}
 
 
-		private void ExecNeg(Instruction i)
+
+		private void ExecSymStorN(Instruction i)
 		{
 		{
-			RValue r = m_ValueStack.Pop();
+			this.AssignGenericSymbol(i.Symbol, m_ValueStack.Peek());
+		}
 
 
-			if (r.Type == DataType.Number)
-				m_ValueStack.Push(new RValue(-r.Number));
-			else
-				throw new NotImplementedException("Meta operators");
+
+		private void ExecAssign(Instruction i)
+		{
+			Slice<RValue> rvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2, i.NumVal2, false);
+			Slice<RValue> lvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2 - i.NumVal, i.NumVal, false);
+
+			Internal_MultiAssign(lvalues, rvalues);
+
+			m_ValueStack.CropAtCount(m_ValueStack.Count - i.NumVal - i.NumVal2);
 		}
 		}
-		private void ExecPower(Instruction i)
+
+		private void Internal_MultiAssign(Slice<RValue> lValues, Slice<RValue> rValues)
 		{
 		{
-			RValue r = m_ValueStack.Pop();
-			RValue l = m_ValueStack.Pop();
+			int li = 0;
+			int rValues_Count = rValues.Count;
+			int lValues_Count = lValues.Count;
 
 
-			if (r.Type == DataType.Number && l.Type == DataType.Number)
-				m_ValueStack.Push(new RValue(Math.Pow(l.Number, r.Number)));
-			else
-				throw new NotImplementedException("Meta operators");
+			for (int ri = 0; ri < rValues_Count && li < lValues_Count; ri++, li++)
+			{
+				RValue vv = rValues[ri];
+
+				if ((ri != rValues_Count - 1) || (vv.Type != DataType.Tuple))
+				{
+					Internal_Assign(lValues[li], vv.ToSingleValue());
+				}
+				else
+				{
+					for (int rri = 0, len = vv.Tuple.Length; rri < len && li < lValues_Count; rri++, li++)
+					{
+						Internal_Assign(lValues[li], vv.Tuple[rri].ToSingleValue());
+					}
+				}
+			}
 		}
 		}
 
 
-		private void ExecMul(Instruction i)
+
+
+
+
+
+
+
+
+
+		private int ExecAdd(Instruction i, int instructionPtr)
 		{
 		{
 			RValue r = m_ValueStack.Pop();
 			RValue r = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 
 
-			if (r.Type == DataType.Number && l.Type == DataType.Number)
-				m_ValueStack.Push(new RValue(l.Number * r.Number));
-			else
-				throw new NotImplementedException("Meta operators");
+			double? rn = r.AsNumber();
+			double? ln = l.AsNumber();
+
+			if (ln.HasValue && rn.HasValue)
+			{
+				m_ValueStack.Push(new RValue(ln.Value + rn.Value));
+				return instructionPtr;
+			}
+			else 
+			{
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__add", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
+			}
 		}
 		}
 
 
-		private void ExecEq(Instruction i)
+		private int ExecSub(Instruction i, int instructionPtr)
 		{
 		{
 			RValue r = m_ValueStack.Pop();
 			RValue r = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 
 
-			m_ValueStack.Push(new RValue(r.Equals(l)));
+			double? rn = r.AsNumber();
+			double? ln = l.AsNumber();
+
+			if (ln.HasValue && rn.HasValue)
+			{
+				m_ValueStack.Push(new RValue(ln.Value - rn.Value));
+				return instructionPtr;
+			}
+			else
+			{
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__sub", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
+			}
 		}
 		}
 
 
-		private void ExecLess(Instruction i)
+
+		private int ExecMul(Instruction i, int instructionPtr)
 		{
 		{
 			RValue r = m_ValueStack.Pop();
 			RValue r = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 
 
-			if (r.Type == DataType.Number && r.Type == DataType.Number)
+			double? rn = r.AsNumber();
+			double? ln = l.AsNumber();
+
+			if (ln.HasValue && rn.HasValue)
 			{
 			{
-				m_ValueStack.Push(new RValue(l.Number < r.Number));
+				m_ValueStack.Push(new RValue(ln.Value * rn.Value));
+				return instructionPtr;
 			}
 			}
 			else
 			else
 			{
 			{
-				throw new NotImplementedException("Comparison between non numbers!");
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__mul", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
 			}
 			}
-		}
-
-		private void ExecLessEq(Instruction i)
+		}		
+		
+		private int ExecMod(Instruction i, int instructionPtr)
 		{
 		{
 			RValue r = m_ValueStack.Pop();
 			RValue r = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 
 
-			if (r.Type == DataType.Number && r.Type == DataType.Number)
+			double? rn = r.AsNumber();
+			double? ln = l.AsNumber();
+
+			if (ln.HasValue && rn.HasValue)
 			{
 			{
-				m_ValueStack.Push(new RValue(l.Number <= r.Number));
+				m_ValueStack.Push(new RValue(Math.IEEERemainder(ln.Value, rn.Value)));
+				return instructionPtr;
 			}
 			}
 			else
 			else
 			{
 			{
-				throw new NotImplementedException("Comparison between non numbers!");
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__div", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
 			}
 			}
 		}
 		}
 
 
-		private void ExecDiv(Instruction i)
+		private int ExecDiv(Instruction i, int instructionPtr)
 		{
 		{
 			RValue r = m_ValueStack.Pop();
 			RValue r = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 
 
-			if (r.Type == DataType.Number && l.Type == DataType.Number)
-				m_ValueStack.Push(new RValue(l.Number / r.Number));
+			double? rn = r.AsNumber();
+			double? ln = l.AsNumber();
+
+			if (ln.HasValue && rn.HasValue)
+			{
+				m_ValueStack.Push(new RValue(ln.Value / rn.Value));
+				return instructionPtr;
+			}
 			else
 			else
-				throw new NotImplementedException("Meta operators");
+			{
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__div", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
+			}
 		}
 		}
+		private int ExecPower(Instruction i, int instructionPtr)
+		{
+			RValue r = m_ValueStack.Pop();
+			RValue l = m_ValueStack.Pop();
 
 
+			double? rn = r.AsNumber();
+			double? ln = l.AsNumber();
 
 
-		private void Internal_Assign(LRef l, RValue r)
-		{
-			if (l.i_Type == LRefType.Index)
+			if (ln.HasValue && rn.HasValue)
 			{
 			{
-				l.i_TableRefObject.Table[l.i_TableRefIndex] = r;
+				m_ValueStack.Push(new RValue(Math.Pow(ln.Value, rn.Value)));
+				return instructionPtr;
 			}
 			}
 			else
 			else
 			{
 			{
-				this.AssignGenericSymbol(l, r.ToSimplestValue());
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__pow", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
 			}
 			}
+
 		}
 		}
 
 
-		private void Internal_Assign(RValue l, RValue r)
+
+		private int ExecNeg(Instruction i, int instructionPtr)
 		{
 		{
-			if (l.Type == DataType.Symbol)
+			RValue r = m_ValueStack.Pop();
+			double? rn = r.AsNumber();
+
+			if (rn.HasValue)
 			{
 			{
-				Internal_Assign(l.Symbol, r);
+				m_ValueStack.Push(new RValue(-rn.Value));
+				return instructionPtr;
 			}
 			}
+
+			if (r.Type == DataType.Number)
+				m_ValueStack.Push(new RValue(-r.Number));
 			else
 			else
 			{
 			{
-				throw new NotImplementedException("How should we manage this ?");
+				int ip = Internal_InvokeUnaryMetaMethod(r, "__unm", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Arithmetic on non number");
 			}
 			}
+
+			return instructionPtr;
 		}
 		}
 
 
-		private void ExecIndexGet(Instruction i, bool methodCall)
+
+		private int ExecEq(Instruction i, int instructionPtr)
 		{
 		{
-			RValue indexValue = m_ValueStack.Pop();
-			RValue baseValue = m_ValueStack.Pop();
+			RValue r = m_ValueStack.Pop();
+			RValue l = m_ValueStack.Pop();
 
 
-			if (baseValue.Type != DataType.Table)
+			if (object.ReferenceEquals(r, l))
 			{
 			{
-				throw new NotImplementedException("META! : Can't index non-table yet");
+				m_ValueStack.Push(new RValue(true));
+			}
+			else if (r.Type != l.Type)
+			{
+				m_ValueStack.Push(new RValue(false));
+			}
+			else if ((l.Type == DataType.Table || l.Type == DataType.UserData) && (l.Meta != null) && (l.Meta == r.Meta))
+			{
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__eq", instructionPtr);
+				if (ip < 0)
+					m_ValueStack.Push(new RValue(r.Equals(l)));
+				else
+					return ip;
 			}
 			}
 			else
 			else
 			{
 			{
-				RValue v = baseValue.Table[indexValue];
-				m_ValueStack.Push(v.AsReadOnly());
+				m_ValueStack.Push(new RValue(r.Equals(l)));
 			}
 			}
 
 
-			if (methodCall)
-				m_ValueStack.Push(baseValue);
+			return instructionPtr;
 		}
 		}
 
 
-		private void ExecIndexRef(Instruction i, bool keepOnStack)
+		private int ExecLess(Instruction i, int instructionPtr)
 		{
 		{
-			RValue indexValue = m_ValueStack.Pop();
-			RValue baseValue = keepOnStack ? m_ValueStack.Peek() : m_ValueStack.Pop();
+			RValue r = m_ValueStack.Pop();
+			RValue l = m_ValueStack.Pop();
 
 
-			if (baseValue.Type != DataType.Table)
+			if (l.Type == DataType.Number && r.Type == DataType.Number)
 			{
 			{
-				throw new NotImplementedException("META! : Can't index non-table yet");
+				m_ValueStack.Push(new RValue(l.Number < r.Number));
+			}
+			else if (l.Type == DataType.String && r.Type == DataType.String)
+			{
+				m_ValueStack.Push(new RValue(l.String.CompareTo(r.String) < 0));
 			}
 			}
 			else
 			else
 			{
 			{
-				LRef s = LRef.ObjIndex(baseValue, indexValue);
-				m_ValueStack.Push(new RValue(s));
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__lt", instructionPtr);
+				if (ip < 0)
+					throw new ScriptRuntimeException(null, "Can't compare on non number non string");
+				else
+					return ip;
 			}
 			}
+
+			return instructionPtr;
 		}
 		}
 
 
-		private void ExecStore(Instruction i)
+		private int ExecLessEq(Instruction i, int instructionPtr)
 		{
 		{
 			RValue r = m_ValueStack.Pop();
 			RValue r = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 			RValue l = m_ValueStack.Pop();
 
 
-			Internal_Assign(l, r);
-		}
+			if (l.Type == DataType.Number && r.Type == DataType.Number)
+			{
+				m_ValueStack.Push(new RValue(l.Number <= r.Number));
+			}
+			else if (l.Type == DataType.String && r.Type == DataType.String)
+			{
+				m_ValueStack.Push(new RValue(l.String.CompareTo(r.String) <= 0));
+			}
+			else
+			{
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__le", instructionPtr);
+				if (ip < 0)
+				{
+					ip = Internal_InvokeBinaryMetaMethod(r, l, "__lt", instructionPtr);
 
 
+					if (ip < 0)
+						throw new ScriptRuntimeException(null, "Can't compare on non number non string");
+					else
+						return ip;
+				}
+				else
+					return ip;
+			}
 
 
-		private void ExecSymStorN(Instruction i)
-		{
-			this.AssignGenericSymbol(i.Symbol, m_ValueStack.Peek());
+			return instructionPtr;
 		}
 		}
 
 
-
-		private void ExecAssign(Instruction i)
+		private int ExecLen(Instruction i, int instructionPtr)
 		{
 		{
-			Slice<RValue> rvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2, i.NumVal2, false);
-			Slice<RValue> lvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2 - i.NumVal, i.NumVal, false);
+			RValue r = m_ValueStack.Pop();
 
 
-			Internal_MultiAssign(lvalues, rvalues);
+			if (r.Type == DataType.String)
+				m_ValueStack.Push(new RValue(r.String.Length));
+			else
+			{
+				int ip = Internal_InvokeUnaryMetaMethod(r, "__len", instructionPtr);
+				if (ip >= 0) 
+					return ip;
+				else if (r.Type == DataType.Table)
+					m_ValueStack.Push(new RValue(r.Table.Length));
+				else 
+					throw new ScriptRuntimeException(null, "Arithmetic on non number");
+			}
 
 
-			m_ValueStack.CropAtCount(m_ValueStack.Count - i.NumVal - i.NumVal2);
+			return instructionPtr;
 		}
 		}
 
 
-		private void Internal_MultiAssign(Slice<RValue> lValues, Slice<RValue> rValues)
+		private int ExecConcat(Instruction i, int instructionPtr)
 		{
 		{
-			int li = 0;
-			int rValues_Count = rValues.Count;
-			int lValues_Count = lValues.Count;
+			RValue r = m_ValueStack.Pop();
+			RValue l = m_ValueStack.Pop();
 
 
-			for (int ri = 0; ri < rValues_Count && li < lValues_Count; ri++, li++)
-			{
-				RValue vv = rValues[ri];
+			string rs = r.AsSimpleString();
+			string ls = l.AsSimpleString();
 
 
-				if ((ri != rValues_Count - 1) || (vv.Type != DataType.Tuple))
-				{
-					Internal_Assign(lValues[li], vv.ToSingleValue());
-				}
-				else
-				{
-					for (int rri = 0, len = vv.Tuple.Length; rri < len && li < lValues_Count; rri++, li++)
-					{
-						Internal_Assign(lValues[li], vv.Tuple[rri].ToSingleValue());
-					}
-				}
+			if (rs != null && ls != null)
+			{
+				m_ValueStack.Push(new RValue(ls + rs));
+				return instructionPtr;
 			}
 			}
+			else
+			{
+				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__concat", instructionPtr);
+				if (ip >= 0) return ip;
+				else throw new ScriptRuntimeException(null, "Concatenation on non strings");
+			}
+
 		}
 		}
+
+
+
+
+
+
+
+
 	}
 	}
 }
 }

+ 56 - 0
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs

@@ -9,6 +9,62 @@ namespace MoonSharp.Interpreter.Execution.VM
 {
 {
 	sealed partial class Processor
 	sealed partial class Processor
 	{
 	{
+		private int Internal_InvokeUnaryMetaMethod(RValue op1, string eventName, int instructionPtr)
+		{
+			RValue m = null;
+
+			if (op1.Meta != null)
+			{
+				RValue meta1 = op1.Meta.Table.RawGet(eventName);
+				if (meta1 != null && meta1.Type != DataType.Nil)
+					m = meta1;
+			}
+
+			if (m != null)
+			{
+				m_ValueStack.Push(m);
+				m_ValueStack.Push(op1);
+				return Internal_ExecCall(1, instructionPtr);
+			}
+			else
+			{
+				return -1;
+			}
+		}
+		private int Internal_InvokeBinaryMetaMethod(RValue l, RValue r, string eventName, int instructionPtr)
+		{
+			var m = Internal_GetBinHandler(l, r, eventName);
+
+			if (m != null)
+			{
+				m_ValueStack.Push(m);
+				m_ValueStack.Push(l);
+				m_ValueStack.Push(r);
+				return Internal_ExecCall(2, instructionPtr);
+			}
+			else
+			{
+				return -1;
+			}
+		}
+
+		private RValue Internal_GetBinHandler(RValue op1, RValue op2, string eventName)
+		{
+			if (op1.Meta != null)
+			{
+				RValue meta1 = op1.Meta.Table.RawGet(eventName);
+				if (meta1 != null && meta1.Type != DataType.Nil)
+					return meta1;
+			}
+			if (op2.Meta != null)
+			{
+				RValue meta2 = op2.Meta.Table.RawGet(eventName);
+				if (meta2 != null && meta2.Type != DataType.Nil)
+					return meta2;
+			}
+			return null;
+		}
+
 
 
 		private RValue[] StackTopToArray(int items, bool pop)
 		private RValue[] StackTopToArray(int items, bool pop)
 		{
 		{

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

@@ -11,7 +11,7 @@ namespace MoonSharp.Interpreter
 	{
 	{
 		public static Table RegisterModuleType(this Table table, Type t)
 		public static Table RegisterModuleType(this Table table, Type t)
 		{
 		{
-			foreach (MethodInfo mi in t.GetMethods(BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public).Where(_mi => _mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).Length > 0))
+			foreach (MethodInfo mi in t.GetMethods(BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic).Where(_mi => _mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).Length > 0))
 			{
 			{
 				MoonSharpMethodAttribute attr = (MoonSharpMethodAttribute)mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).First();
 				MoonSharpMethodAttribute attr = (MoonSharpMethodAttribute)mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).First();
 
 
@@ -42,7 +42,7 @@ namespace MoonSharp.Interpreter
 		{
 		{
 			Type t = o.GetType();
 			Type t = o.GetType();
 
 
-			foreach (MethodInfo mi in t.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Public).Where(_mi => _mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).Length > 0))
+			foreach (MethodInfo mi in t.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic).Where(_mi => _mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).Length > 0))
 			{
 			{
 				MoonSharpMethodAttribute attr = (MoonSharpMethodAttribute)mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).First();
 				MoonSharpMethodAttribute attr = (MoonSharpMethodAttribute)mi.GetCustomAttributes(typeof(MoonSharpMethodAttribute), false).First();
 
 

+ 1 - 1
src/MoonSharpTests/Program.cs

@@ -12,7 +12,7 @@ namespace MoonSharpTests
 {
 {
 	class Program
 	class Program
 	{
 	{
-		public const string RESTRICT_TEST = "LoopWithReturn";
+		public const string RESTRICT_TEST = null;//"LoopWithReturn";
 
 
 		static void Main(string[] args)
 		static void Main(string[] args)
 		{
 		{