Browse Source

table.sort

Xanathar 11 years ago
parent
commit
09eeb547f0

+ 2 - 2
src/MoonSharp.Interpreter/CoreLib/BasicMethods.cs

@@ -168,7 +168,7 @@ namespace MoonSharp.Interpreter.CoreLib
 				if ((args[i].Type == DataType.Table) && (args[i].Table.MetaTable != null) &&
 				if ((args[i].Type == DataType.Table) && (args[i].Table.MetaTable != null) &&
 					(args[i].Table.MetaTable.RawGet("__tostring") != null))
 					(args[i].Table.MetaTable.RawGet("__tostring") != null))
 				{
 				{
-					var v = executionContext.GetOwnerScript().Call(args[i].Table.MetaTable.RawGet("__tostring"), args[i]);
+					var v = executionContext.GetScript().Call(args[i].Table.MetaTable.RawGet("__tostring"), args[i]);
 
 
 					if (v.Type != DataType.String)
 					if (v.Type != DataType.String)
 						throw new ScriptRuntimeException("'tostring' must return a string to 'print'");
 						throw new ScriptRuntimeException("'tostring' must return a string to 'print'");
@@ -181,7 +181,7 @@ namespace MoonSharp.Interpreter.CoreLib
 				}
 				}
 			}
 			}
 
 
-			executionContext.GetOwnerScript().DebugPrint(sb.ToString());
+			executionContext.GetScript().DebugPrint(sb.ToString());
 
 
 			return DynValue.Nil;
 			return DynValue.Nil;
 		}
 		}

+ 4 - 4
src/MoonSharp.Interpreter/CoreLib/LoadMethods.cs

@@ -28,7 +28,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		{
 		{
 			try
 			try
 			{
 			{
-				Script S = executionContext.GetOwnerScript();
+				Script S = executionContext.GetScript();
 				DynValue ld = args.AsType(0, "load", DataType.String, false);
 				DynValue ld = args.AsType(0, "load", DataType.String, false);
 				DynValue source = args.AsType(1, "load", DataType.String, true);
 				DynValue source = args.AsType(1, "load", DataType.String, true);
 				DynValue env = args.AsType(3, "load", DataType.Table, true);
 				DynValue env = args.AsType(3, "load", DataType.Table, true);
@@ -54,7 +54,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		{
 		{
 			try
 			try
 			{
 			{
-				Script S = executionContext.GetOwnerScript();
+				Script S = executionContext.GetScript();
 				DynValue filename = args.AsType(0, "loadfile", DataType.String, false);
 				DynValue filename = args.AsType(0, "loadfile", DataType.String, false);
 				DynValue env = args.AsType(2, "loadfile", DataType.Table, true);
 				DynValue env = args.AsType(2, "loadfile", DataType.Table, true);
 
 
@@ -78,7 +78,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		{
 		{
 			try
 			try
 			{
 			{
-				Script S = executionContext.GetOwnerScript();
+				Script S = executionContext.GetScript();
 				DynValue v = args.AsType(0, "dofile", DataType.String, false);
 				DynValue v = args.AsType(0, "dofile", DataType.String, false);
 
 
 				DynValue fn = S.LoadFile(v.String);
 				DynValue fn = S.LoadFile(v.String);
@@ -115,7 +115,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		[MoonSharpMethod]
 		[MoonSharpMethod]
 		public static DynValue __require_clr_impl(ScriptExecutionContext executionContext, CallbackArguments args)
 		public static DynValue __require_clr_impl(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
 		{
-			Script S = executionContext.GetOwnerScript();
+			Script S = executionContext.GetScript();
 			DynValue v = args.AsType(0, "__require_clr_impl", DataType.String, false);
 			DynValue v = args.AsType(0, "__require_clr_impl", DataType.String, false);
 
 
 			DynValue fn = S.RequireModule(v.String);
 			DynValue fn = S.RequireModule(v.String);

+ 2 - 2
src/MoonSharp.Interpreter/CoreLib/MathModule.cs

@@ -237,7 +237,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		{
 		{
 			DynValue m = args.AsType(0, "random", DataType.Number, true);
 			DynValue m = args.AsType(0, "random", DataType.Number, true);
 			DynValue n = args.AsType(1, "random", DataType.Number, true);
 			DynValue n = args.AsType(1, "random", DataType.Number, true);
-			Random R = executionContext.GetOwnerScript().RandomGenerator;
+			Random R = executionContext.GetScript().RandomGenerator;
 			double d;
 			double d;
 
 
 			if (m.IsNil() && n.IsNil())
 			if (m.IsNil() && n.IsNil())
@@ -262,7 +262,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		public static DynValue randomseed(ScriptExecutionContext executionContext, CallbackArguments args)
 		public static DynValue randomseed(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
 		{
 			DynValue arg = args.AsType(0, "randomseed", DataType.Number, false);
 			DynValue arg = args.AsType(0, "randomseed", DataType.Number, false);
-			executionContext.GetOwnerScript().ReseedRandomGenerator(arg.Number);
+			executionContext.GetScript().ReseedRandomGenerator(arg.Number);
 			return DynValue.Nil;
 			return DynValue.Nil;
 		}
 		}
 
 

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

@@ -44,7 +44,7 @@ namespace MoonSharp.Interpreter.CoreLib
 
 
 			if (obj.Type.CanHaveTypeMetatables())
 			if (obj.Type.CanHaveTypeMetatables())
 			{
 			{
-				meta = executionContext.GetOwnerScript().GetTypeMetatable(obj.Type);
+				meta = executionContext.GetScript().GetTypeMetatable(obj.Type);
 			}
 			}
 			
 			
 			
 			

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

@@ -36,7 +36,7 @@ namespace MoonSharp.Interpreter.CoreLib
 			DynValue s = args.AsType(0, "gmatch", DataType.String, false);
 			DynValue s = args.AsType(0, "gmatch", DataType.String, false);
 			DynValue p = args.AsType(1, "gmatch", DataType.String, false);
 			DynValue p = args.AsType(1, "gmatch", DataType.String, false);
 
 
-			return PatternMatching.GMatch(executionContext.GetOwnerScript(), s.String, p.String);
+			return PatternMatching.GMatch(executionContext.GetScript(), s.String, p.String);
 		}
 		}
 
 
 		[MoonSharpMethod()]
 		[MoonSharpMethod()]

+ 95 - 20
src/MoonSharp.Interpreter/CoreLib/TableModule.cs

@@ -28,7 +28,7 @@ namespace MoonSharp.Interpreter.CoreLib
 		public static DynValue pack(ScriptExecutionContext executionContext, CallbackArguments args)
 		public static DynValue pack(ScriptExecutionContext executionContext, CallbackArguments args)
 		{
 		{
 			DynValue s = args[0];
 			DynValue s = args[0];
-			Table t = new Table(executionContext.GetOwnerScript());
+			Table t = new Table(executionContext.GetScript());
 			DynValue v = DynValue.NewTable(t);
 			DynValue v = DynValue.NewTable(t);
 
 
 			if (s.IsNil())
 			if (s.IsNil())
@@ -47,6 +47,79 @@ namespace MoonSharp.Interpreter.CoreLib
 			return v;
 			return v;
 		}
 		}
 
 
+		[MoonSharpMethod]
+		public static DynValue sort(ScriptExecutionContext executionContext, CallbackArguments args)
+		{
+			DynValue vlist = args.AsType(0, "sort", DataType.Table, false);
+			DynValue lt = args[1];
+
+			if (lt.Type != DataType.Function && lt.Type != DataType.ClrFunction && lt.Type != DataType.Nil)
+				args.AsType(1, "sort", DataType.Function, true); // this throws
+
+			int end = GetTableLength(executionContext, vlist);
+
+			List<DynValue> values = new List<DynValue>();
+
+			for (int i = 1; i < end; i++)
+				values.Add(vlist.Table[i]);
+
+			values.Sort((a, b) => SortComparer(executionContext, a, b, lt));
+
+			for (int i = 0; i < values.Count; i++)
+			{
+				vlist.Table[i + 1] = values[i];
+			}
+
+			return vlist;
+		}
+
+		private static int SortComparer(ScriptExecutionContext executionContext, DynValue a, DynValue b, DynValue lt)
+		{
+			if (lt == null || lt.IsNil())
+			{
+				lt = executionContext.GetBinaryMetamethod(a, b, "__lt");
+
+				if (lt == null || lt.IsNil())
+				{
+					if (a.Type == DataType.Number && b.Type == DataType.Number)
+						return a.Number.CompareTo(b.Number);
+					if (a.Type == DataType.String && b.Type == DataType.String)
+						return a.String.CompareTo(b.String);
+
+					throw ScriptRuntimeException.CompareInvalidType(a, b);
+				}
+				else
+				{
+					return LuaComparerToClrComparer(
+						executionContext.GetScript().Call(lt, a, b),
+						executionContext.GetScript().Call(lt, b, a));
+				}
+			}
+			else
+			{
+				return LuaComparerToClrComparer(
+					executionContext.GetScript().Call(lt, a, b),
+					executionContext.GetScript().Call(lt, b, a));
+			}
+		}
+
+		private static int LuaComparerToClrComparer(DynValue dynValue1, DynValue dynValue2)
+		{
+			bool v1 = dynValue1.CastToBool();
+			bool v2 = dynValue2.CastToBool();
+
+			if (v1 && !v2)
+				return -1;
+			if (v2 && !v1)
+				return 1;
+
+			return 0;
+		}
+
+
+
+
+
 		//table.concat (list [, sep [, i [, j]]])
 		//table.concat (list [, sep [, i [, j]]])
 		//Given a list where all elements are strings or numbers, returns the string list[i]..sep..list[i+1] (...) sep..list[j]. 
 		//Given a list where all elements are strings or numbers, returns the string list[i]..sep..list[i+1] (...) sep..list[j]. 
 		//The default value for sep is the empty string, the default for i is 1, and the default for j is #list. If i is greater 
 		//The default value for sep is the empty string, the default for i is 1, and the default for j is #list. If i is greater 
@@ -59,8 +132,6 @@ namespace MoonSharp.Interpreter.CoreLib
 			DynValue vstart = args.AsType(2, "concat", DataType.Number, true);
 			DynValue vstart = args.AsType(2, "concat", DataType.Number, true);
 			DynValue vend = args.AsType(3, "concat", DataType.Number, true);
 			DynValue vend = args.AsType(3, "concat", DataType.Number, true);
 
 
-
-
 			Table list = vlist.Table;
 			Table list = vlist.Table;
 			string sep = vsep.IsNil() ? "" : vsep.String;
 			string sep = vsep.IsNil() ? "" : vsep.String;
 			int start = vstart.IsNilOrNan() ? 1 : (int)vstart.Number;
 			int start = vstart.IsNilOrNan() ? 1 : (int)vstart.Number;
@@ -68,23 +139,7 @@ namespace MoonSharp.Interpreter.CoreLib
 
 
 			if (vend.IsNilOrNan())
 			if (vend.IsNilOrNan())
 			{
 			{
-				DynValue __len = executionContext.GetMetamethod(vlist, "__len");
-
-				if (__len != null)
-				{
-					DynValue lenv = executionContext.GetOwnerScript().Call(__len, vlist);
-
-					double? len = lenv.CastToNumber();
-
-					if (len == null)
-						throw new ScriptRuntimeException("object length is not a number");
-
-					end = (int)len;
-				}
-				else
-				{
-					end = (int)vlist.Table.Length;
-				}
+				end = GetTableLength(executionContext, vlist);
 			}
 			}
 			else 
 			else 
 			{
 			{
@@ -115,6 +170,26 @@ namespace MoonSharp.Interpreter.CoreLib
 			return DynValue.NewString(sb.ToString());
 			return DynValue.NewString(sb.ToString());
 		}
 		}
 
 
+		private static int GetTableLength(ScriptExecutionContext executionContext, DynValue vlist)
+		{
+			DynValue __len = executionContext.GetMetamethod(vlist, "__len");
+
+			if (__len != null)
+			{
+				DynValue lenv = executionContext.GetScript().Call(__len, vlist);
+
+				double? len = lenv.CastToNumber();
+
+				if (len == null)
+					throw new ScriptRuntimeException("object length is not a number");
+
+				return (int)len;
+			}
+			else
+			{
+				return (int)vlist.Table.Length;
+			}
+		}
 	}
 	}
 
 
 
 

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

@@ -59,9 +59,14 @@ namespace MoonSharp.Interpreter.Execution
 			return DynValue.NewTailCallReq(meta, args);
 			return DynValue.NewTailCallReq(meta, args);
 		}
 		}
 
 
-		public Script GetOwnerScript()
+		public DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
 		{
 		{
-			return m_Processor.GetOwnerScript();
+			return m_Processor.GetBinaryMetamethod(op1, op2, eventName);
+		}
+
+		public Script GetScript()
+		{
+			return m_Processor.GetScript();
 		}
 		}
 
 
 		private bool CheckUpValue(SymbolRef symref)
 		private bool CheckUpValue(SymbolRef symref)

+ 21 - 1
src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_IExecutionContext.cs

@@ -34,6 +34,26 @@ namespace MoonSharp.Interpreter.Execution.VM
 			}
 			}
 		}
 		}
 
 
+		internal DynValue GetBinaryMetamethod(DynValue op1, DynValue op2, string eventName)
+		{
+			var op1_MetaTable = GetMetatable(op1);
+			var op2_MetaTable = GetMetatable(op2);
+
+			if (op1_MetaTable != null)
+			{
+				DynValue meta1 = op1_MetaTable.RawGet(eventName);
+				if (meta1 != null && meta1.Type != DataType.Nil)
+					return meta1;
+			}
+			if (op2_MetaTable != null)
+			{
+				DynValue meta2 = op2_MetaTable.RawGet(eventName);
+				if (meta2 != null && meta2.Type != DataType.Nil)
+					return meta2;
+			}
+			return null;
+		}
+
 		internal DynValue GetMetamethod(DynValue value, string metamethod)
 		internal DynValue GetMetamethod(DynValue value, string metamethod)
 		{
 		{
 			var metatable = GetMetatable(value);
 			var metatable = GetMetatable(value);
@@ -49,7 +69,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 			return metameth;
 			return metameth;
 		}
 		}
 
 
-		internal Script GetOwnerScript()
+		internal Script GetScript()
 		{
 		{
 			return m_Script;
 			return m_Script;
 		}
 		}

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

@@ -75,7 +75,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 		}
 		}
 		private int Internal_InvokeBinaryMetaMethod(DynValue l, DynValue r, string eventName, int instructionPtr, DynValue extraPush = null)
 		private int Internal_InvokeBinaryMetaMethod(DynValue l, DynValue r, string eventName, int instructionPtr, DynValue extraPush = null)
 		{
 		{
-			var m = Internal_GetBinHandler(l, r, eventName);
+			var m = GetBinaryMetamethod(l, r, eventName);
 
 
 			if (m != null)
 			if (m != null)
 			{
 			{
@@ -93,25 +93,7 @@ namespace MoonSharp.Interpreter.Execution.VM
 			}
 			}
 		}
 		}
 
 
-		private DynValue Internal_GetBinHandler(DynValue op1, DynValue op2, string eventName)
-		{
-			var op1_MetaTable = GetMetatable(op1);
-			var op2_MetaTable = GetMetatable(op2);
 
 
-			if (op1_MetaTable != null)
-			{
-				DynValue meta1 = op1_MetaTable.RawGet(eventName);
-				if (meta1 != null && meta1.Type != DataType.Nil)
-					return meta1;
-			}
-			if (op2_MetaTable != null)
-			{
-				DynValue meta2 = op2_MetaTable.RawGet(eventName);
-				if (meta2 != null && meta2.Type != DataType.Nil)
-					return meta2;
-			}
-			return null;
-		}
 
 
 
 
 		private DynValue[] StackTopToArray(int items, bool pop)
 		private DynValue[] StackTopToArray(int items, bool pop)