Browse Source

lots of optimizations

Xanathar 11 years ago
parent
commit
8de5c74230

+ 39 - 0
src/MoonSharp.Interpreter/CoreLib/OsMethods.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MoonSharp.Interpreter.Execution;
+
+namespace MoonSharp.Interpreter.CoreLib
+{
+		[MoonSharpModule(Namespace = "os")]
+	public  class OsMethods
+	{
+		static DateTime Time0 = DateTime.UtcNow;
+		static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+
+		[MoonSharpMethod]
+		public static DynValue clock(ScriptExecutionContext executionContext, CallbackArguments args)
+		{
+			return DynValue.NewNumber((DateTime.UtcNow - Time0).TotalSeconds);
+		}
+
+		[MoonSharpMethod]
+		public static DynValue time(ScriptExecutionContext executionContext, CallbackArguments args)
+		{
+			DateTime date = DateTime.UtcNow;
+
+			if (args.Count > 0)
+			{
+
+
+			}
+
+
+			return DynValue.NewNumber(Math.Floor(( date - Epoch).TotalSeconds));
+
+
+		}
+		
+	}
+}

+ 747 - 0
src/MoonSharp.Interpreter/CoreLib/Patterns/Tools.cs

@@ -0,0 +1,747 @@
+//
+// This part taken from KopiLua - https://github.com/NLua/KopiLua
+//
+// =========================================================================================================
+//
+// Kopi Lua License
+// ----------------
+// MIT License for KopiLua
+// Copyright (c) 2012 LoDC
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
+// associated documentation files (the "Software"), to deal in the Software without restriction,
+// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+// subject to the following conditions:
+// The above copyright notice and this permission notice shall be included in all copies or substantial
+// portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// ===============================================================================
+// Lua License
+// -----------
+// Lua is licensed under the terms of the MIT license reproduced below.
+// This means that Lua is free software and can be used for both academic
+// and commercial purposes at absolutely no cost.
+// For details and rationale, see http://www.lua.org/license.html .
+// ===============================================================================
+// Copyright (C) 1994-2008 Lua.org, PUC-Rio.
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+
+#region Usings
+using System;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Globalization;
+
+
+#endregion
+
+namespace AT.MIN
+{
+	public static class Tools
+	{
+		#region Public Methods
+		#region IsNumericType
+		/// <summary>
+		/// Determines whether the specified value is of numeric type.
+		/// </summary>
+		/// <param name="o">The object to check.</param>
+		/// <returns>
+		/// 	<c>true</c> if o is a numeric type; otherwise, <c>false</c>.
+		/// </returns>
+		public static bool IsNumericType(object o)
+		{
+			return (o is byte ||
+				o is sbyte ||
+				o is short ||
+				o is ushort ||
+				o is int ||
+				o is uint ||
+				o is long ||
+				o is ulong ||
+				o is float ||
+				o is double ||
+				o is decimal);
+		}
+		#endregion
+		#region IsPositive
+		/// <summary>
+		/// Determines whether the specified value is positive.
+		/// </summary>
+		/// <param name="Value">The value.</param>
+		/// <param name="ZeroIsPositive">if set to <c>true</c> treats 0 as positive.</param>
+		/// <returns>
+		/// 	<c>true</c> if the specified value is positive; otherwise, <c>false</c>.
+		/// </returns>
+		public static bool IsPositive(object Value, bool ZeroIsPositive)
+		{
+			switch (Type.GetTypeCode(Value.GetType()))
+			{
+				case TypeCode.SByte:
+					return (ZeroIsPositive ? (sbyte)Value >= 0 : (sbyte)Value > 0);
+				case TypeCode.Int16:
+					return (ZeroIsPositive ? (short)Value >= 0 : (short)Value > 0);
+				case TypeCode.Int32:
+					return (ZeroIsPositive ? (int)Value >= 0 : (int)Value > 0);
+				case TypeCode.Int64:
+					return (ZeroIsPositive ? (long)Value >= 0 : (long)Value > 0);
+				case TypeCode.Single:
+					return (ZeroIsPositive ? (float)Value >= 0 : (float)Value > 0);
+				case TypeCode.Double:
+					return (ZeroIsPositive ? (double)Value >= 0 : (double)Value > 0);
+				case TypeCode.Decimal:
+					return (ZeroIsPositive ? (decimal)Value >= 0 : (decimal)Value > 0);
+				case TypeCode.Byte:
+					return (ZeroIsPositive ? true : (byte)Value > 0);
+				case TypeCode.UInt16:
+					return (ZeroIsPositive ? true : (ushort)Value > 0);
+				case TypeCode.UInt32:
+					return (ZeroIsPositive ? true : (uint)Value > 0);
+				case TypeCode.UInt64:
+					return (ZeroIsPositive ? true : (ulong)Value > 0);
+				case TypeCode.Char:
+					return (ZeroIsPositive ? true : (char)Value != '\0');
+				default:
+					return false;
+			}
+		}
+		#endregion
+		#region ToUnsigned
+		/// <summary>
+		/// Converts the specified values boxed type to its correpsonding unsigned
+		/// type.
+		/// </summary>
+		/// <param name="Value">The value.</param>
+		/// <returns>A boxed numeric object whos type is unsigned.</returns>
+		public static object ToUnsigned(object Value)
+		{
+			switch (Type.GetTypeCode(Value.GetType()))
+			{
+				case TypeCode.SByte:
+					return (byte)((sbyte)Value);
+				case TypeCode.Int16:
+					return (ushort)((short)Value);
+				case TypeCode.Int32:
+					return (uint)((int)Value);
+				case TypeCode.Int64:
+					return (ulong)((long)Value);
+
+				case TypeCode.Byte:
+					return Value;
+				case TypeCode.UInt16:
+					return Value;
+				case TypeCode.UInt32:
+					return Value;
+				case TypeCode.UInt64:
+					return Value;
+
+				case TypeCode.Single:
+					return (UInt32)((float)Value);
+				case TypeCode.Double:
+					return (ulong)((double)Value);
+				case TypeCode.Decimal:
+					return (ulong)((decimal)Value);
+
+				default:
+					return null;
+			}
+		}
+		#endregion
+		#region ToInteger
+		/// <summary>
+		/// Converts the specified values boxed type to its correpsonding integer
+		/// type.
+		/// </summary>
+		/// <param name="Value">The value.</param>
+		/// <returns>A boxed numeric object whos type is an integer type.</returns>
+		public static object ToInteger(object Value, bool Round)
+		{
+			switch (Type.GetTypeCode(Value.GetType()))
+			{
+				case TypeCode.SByte:
+					return Value;
+				case TypeCode.Int16:
+					return Value;
+				case TypeCode.Int32:
+					return Value;
+				case TypeCode.Int64:
+					return Value;
+
+				case TypeCode.Byte:
+					return Value;
+				case TypeCode.UInt16:
+					return Value;
+				case TypeCode.UInt32:
+					return Value;
+				case TypeCode.UInt64:
+					return Value;
+
+				case TypeCode.Single:
+					return (Round ? (int)Math.Round((float)Value) : (int)((float)Value));
+				case TypeCode.Double:
+					return (Round ? (long)Math.Round((double)Value) : (long)((double)Value));
+				case TypeCode.Decimal:
+					return (Round ? Math.Round((decimal)Value) : (decimal)Value);
+
+				default:
+					return null;
+			}
+		}
+		#endregion
+		#region UnboxToLong
+		public static long UnboxToLong(object Value, bool Round)
+		{
+			switch (Type.GetTypeCode(Value.GetType()))
+			{
+				case TypeCode.SByte:
+					return (long)((sbyte)Value);
+				case TypeCode.Int16:
+					return (long)((short)Value);
+				case TypeCode.Int32:
+					return (long)((int)Value);
+				case TypeCode.Int64:
+					return (long)Value;
+
+				case TypeCode.Byte:
+					return (long)((byte)Value);
+				case TypeCode.UInt16:
+					return (long)((ushort)Value);
+				case TypeCode.UInt32:
+					return (long)((uint)Value);
+				case TypeCode.UInt64:
+					return (long)((ulong)Value);
+
+				case TypeCode.Single:
+					return (Round ? (long)Math.Round((float)Value) : (long)((float)Value));
+				case TypeCode.Double:
+					return (Round ? (long)Math.Round((double)Value) : (long)((double)Value));
+				case TypeCode.Decimal:
+					return (Round ? (long)Math.Round((decimal)Value) : (long)((decimal)Value));
+
+				default:
+					return 0;
+			}
+		}
+		#endregion
+		#region ReplaceMetaChars
+		/// <summary>
+		/// Replaces the string representations of meta chars with their corresponding
+		/// character values.
+		/// </summary>
+		/// <param name="input">The input.</param>
+		/// <returns>A string with all string meta chars are replaced</returns>
+		public static string ReplaceMetaChars(string input)
+		{
+			return Regex.Replace(input, @"(\\)(\d{3}|[^\d])?", new MatchEvaluator(ReplaceMetaCharsMatch));
+		}
+		private static string ReplaceMetaCharsMatch(Match m)
+		{
+			// convert octal quotes (like \040)
+			if (m.Groups[2].Length == 3)
+				return Convert.ToChar(Convert.ToByte(m.Groups[2].Value, 8)).ToString();
+			else
+			{
+				// convert all other special meta characters
+				//TODO: \xhhh hex and possible dec !!
+				switch (m.Groups[2].Value)
+				{
+					case "0":           // null
+						return "\0";
+					case "a":           // alert (beep)
+						return "\a";
+					case "b":           // BS
+						return "\b";
+					case "f":           // FF
+						return "\f";
+					case "v":           // vertical tab
+						return "\v";
+					case "r":           // CR
+						return "\r";
+					case "n":           // LF
+						return "\n";
+					case "t":           // Tab
+						return "\t";
+					default:
+						// if neither an octal quote nor a special meta character
+						// so just remove the backslash
+						return m.Groups[2].Value;
+				}
+			}
+		}
+		#endregion
+		#region printf
+		public static void printf(string Format, params object[] Parameters)
+		{
+			Console.Write(Tools.sprintf(Format, Parameters));
+		}
+		#endregion
+		#region fprintf
+		public static void fprintf(TextWriter Destination, string Format, params object[] Parameters)
+		{
+			Destination.Write(Tools.sprintf(Format, Parameters));
+		}
+
+
+		#endregion
+		#region sprintf
+		internal static Regex r = new Regex(@"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])");
+		public static string sprintf(string Format, params object[] Parameters)
+		{
+			#region Variables
+			StringBuilder f = new StringBuilder();
+			//Regex r = new Regex( @"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])" );
+			//"%[parameter][flags][width][.precision][length]type"
+			Match m = null;
+			string w = String.Empty;
+			int defaultParamIx = 0;
+			int paramIx;
+			object o = null;
+
+			bool flagLeft2Right = false;
+			bool flagAlternate = false;
+			bool flagPositiveSign = false;
+			bool flagPositiveSpace = false;
+			bool flagZeroPadding = false;
+			bool flagGroupThousands = false;
+
+			int fieldLength = 0;
+			int fieldPrecision = 0;
+			char shortLongIndicator = '\0';
+			char formatSpecifier = '\0';
+			char paddingCharacter = ' ';
+			#endregion
+
+			// find all format parameters in format string
+			f.Append(Format);
+			m = r.Match(f.ToString());
+			while (m.Success)
+			{
+				#region parameter index
+				paramIx = defaultParamIx;
+				if (m.Groups[1] != null && m.Groups[1].Value.Length > 0)
+				{
+					string val = m.Groups[1].Value.Substring(0, m.Groups[1].Value.Length - 1);
+					paramIx = Convert.ToInt32(val) - 1;
+				};
+				#endregion
+
+				#region format flags
+				// extract format flags
+				flagAlternate = false;
+				flagLeft2Right = false;
+				flagPositiveSign = false;
+				flagPositiveSpace = false;
+				flagZeroPadding = false;
+				flagGroupThousands = false;
+				if (m.Groups[2] != null && m.Groups[2].Value.Length > 0)
+				{
+					string flags = m.Groups[2].Value;
+
+					flagAlternate = (flags.IndexOf('#') >= 0);
+					flagLeft2Right = (flags.IndexOf('-') >= 0);
+					flagPositiveSign = (flags.IndexOf('+') >= 0);
+					flagPositiveSpace = (flags.IndexOf(' ') >= 0);
+					flagGroupThousands = (flags.IndexOf('\'') >= 0);
+
+					// positive + indicator overrides a
+					// positive space character
+					if (flagPositiveSign && flagPositiveSpace)
+						flagPositiveSpace = false;
+				}
+				#endregion
+
+				#region field length
+				// extract field length and 
+				// pading character
+				paddingCharacter = ' ';
+				fieldLength = int.MinValue;
+				if (m.Groups[3] != null && m.Groups[3].Value.Length > 0)
+				{
+					fieldLength = Convert.ToInt32(m.Groups[3].Value);
+					flagZeroPadding = (m.Groups[3].Value[0] == '0');
+				}
+				#endregion
+
+				if (flagZeroPadding)
+					paddingCharacter = '0';
+
+				// left2right allignment overrides zero padding
+				if (flagLeft2Right && flagZeroPadding)
+				{
+					flagZeroPadding = false;
+					paddingCharacter = ' ';
+				}
+
+				#region field precision
+				// extract field precision
+				fieldPrecision = int.MinValue;
+				if (m.Groups[4] != null && m.Groups[4].Value.Length > 0)
+					fieldPrecision = Convert.ToInt32(m.Groups[4].Value);
+				#endregion
+
+				#region short / long indicator
+				// extract short / long indicator
+				shortLongIndicator = Char.MinValue;
+				if (m.Groups[5] != null && m.Groups[5].Value.Length > 0)
+					shortLongIndicator = m.Groups[5].Value[0];
+				#endregion
+
+				#region format specifier
+				// extract format
+				formatSpecifier = Char.MinValue;
+				if (m.Groups[6] != null && m.Groups[6].Value.Length > 0)
+					formatSpecifier = m.Groups[6].Value[0];
+				#endregion
+
+				// default precision is 6 digits if none is specified except
+				if (fieldPrecision == int.MinValue &&
+					formatSpecifier != 's' &&
+					formatSpecifier != 'c' &&
+					Char.ToUpper(formatSpecifier) != 'X' &&
+					formatSpecifier != 'o')
+					fieldPrecision = 6;
+
+				#region get next value parameter
+				// get next value parameter and convert value parameter depending on short / long indicator
+				if (Parameters == null || paramIx >= Parameters.Length)
+					o = null;
+				else
+				{
+					o = Parameters[paramIx];
+
+					if (shortLongIndicator == 'h')
+					{
+						if (o is int)
+							o = (short)((int)o);
+						else if (o is long)
+							o = (short)((long)o);
+						else if (o is uint)
+							o = (ushort)((uint)o);
+						else if (o is ulong)
+							o = (ushort)((ulong)o);
+					}
+					else if (shortLongIndicator == 'l')
+					{
+						if (o is short)
+							o = (long)((short)o);
+						else if (o is int)
+							o = (long)((int)o);
+						else if (o is ushort)
+							o = (ulong)((ushort)o);
+						else if (o is uint)
+							o = (ulong)((uint)o);
+					}
+				}
+				#endregion
+
+				// convert value parameters to a string depending on the formatSpecifier
+				w = String.Empty;
+				switch (formatSpecifier)
+				{
+					#region % - character
+					case '%':   // % character
+						w = "%";
+						break;
+					#endregion
+					#region d - integer
+					case 'd':   // integer
+						w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate,
+										fieldLength, int.MinValue, flagLeft2Right,
+										flagPositiveSign, flagPositiveSpace,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region i - integer
+					case 'i':   // integer
+						goto case 'd';
+					#endregion
+					#region o - octal integer
+					case 'o':   // octal integer - no leading zero
+						w = FormatOct("o", flagAlternate,
+										fieldLength, int.MinValue, flagLeft2Right,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region x - hex integer
+					case 'x':   // hex integer - no leading zero
+						w = FormatHex("x", flagAlternate,
+										fieldLength, fieldPrecision, flagLeft2Right,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region X - hex integer
+					case 'X':   // same as x but with capital hex characters
+						w = FormatHex("X", flagAlternate,
+										fieldLength, fieldPrecision, flagLeft2Right,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region u - unsigned integer
+					case 'u':   // unsigned integer
+						w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate,
+										fieldLength, int.MinValue, flagLeft2Right,
+										false, false,
+										paddingCharacter, ToUnsigned(o));
+						defaultParamIx++;
+						break;
+					#endregion
+					#region c - character
+					case 'c':   // character
+						if (IsNumericType(o))
+							w = Convert.ToChar(o).ToString();
+						else if (o is char)
+							w = ((char)o).ToString();
+						else if (o is string && ((string)o).Length > 0)
+							w = ((string)o)[0].ToString();
+						defaultParamIx++;
+						break;
+					#endregion
+					#region s - string
+					case 's':   // string
+						//string t = "{0" + ( fieldLength != int.MinValue ? "," + ( flagLeft2Right ? "-" : String.Empty ) + fieldLength.ToString() : String.Empty ) + ":s}";
+						w = o.ToString();
+						if (fieldPrecision >= 0)
+							w = w.Substring(0, fieldPrecision);
+
+						if (fieldLength != int.MinValue)
+							if (flagLeft2Right)
+								w = w.PadRight(fieldLength, paddingCharacter);
+							else
+								w = w.PadLeft(fieldLength, paddingCharacter);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region f - double number
+					case 'f':   // double
+						w = FormatNumber((flagGroupThousands ? "n" : "f"), flagAlternate,
+										fieldLength, fieldPrecision, flagLeft2Right,
+										flagPositiveSign, flagPositiveSpace,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region e - exponent number
+					case 'e':   // double / exponent
+						w = FormatNumber("e", flagAlternate,
+										fieldLength, fieldPrecision, flagLeft2Right,
+										flagPositiveSign, flagPositiveSpace,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region E - exponent number
+					case 'E':   // double / exponent
+						w = FormatNumber("E", flagAlternate,
+										fieldLength, fieldPrecision, flagLeft2Right,
+										flagPositiveSign, flagPositiveSpace,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region g - general number
+					case 'g':   // double / exponent
+						w = FormatNumber("g", flagAlternate,
+										fieldLength, fieldPrecision, flagLeft2Right,
+										flagPositiveSign, flagPositiveSpace,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region G - general number
+					case 'G':   // double / exponent
+						w = FormatNumber("G", flagAlternate,
+										fieldLength, fieldPrecision, flagLeft2Right,
+										flagPositiveSign, flagPositiveSpace,
+										paddingCharacter, o);
+						defaultParamIx++;
+						break;
+					#endregion
+					#region p - pointer
+					case 'p':   // pointer
+						if (o is IntPtr)
+#if XBOX || SILVERLIGHT
+							w = ( (IntPtr)o ).ToString();
+#else
+							w = "0x" + ((IntPtr)o).ToString("x");
+#endif
+						defaultParamIx++;
+						break;
+					#endregion
+					#region n - number of processed chars so far
+					case 'n':   // number of characters so far
+						w = FormatNumber("d", flagAlternate,
+										fieldLength, int.MinValue, flagLeft2Right,
+										flagPositiveSign, flagPositiveSpace,
+										paddingCharacter, m.Index);
+						break;
+					#endregion
+					default:
+						w = String.Empty;
+						defaultParamIx++;
+						break;
+				}
+
+				// replace format parameter with parameter value
+				// and start searching for the next format parameter
+				// AFTER the position of the current inserted value
+				// to prohibit recursive matches if the value also
+				// includes a format specifier
+				f.Remove(m.Index, m.Length);
+				f.Insert(m.Index, w);
+				m = r.Match(f.ToString(), m.Index + w.Length);
+			}
+
+			return f.ToString();
+		}
+		#endregion
+		#endregion
+
+		#region Private Methods
+		#region FormatOCT
+		private static string FormatOct(string NativeFormat, bool Alternate,
+											int FieldLength, int FieldPrecision,
+											bool Left2Right,
+											char Padding, object Value)
+		{
+			string w = String.Empty;
+			string lengthFormat = "{0" + (FieldLength != int.MinValue ?
+											"," + (Left2Right ?
+													"-" :
+													String.Empty) + FieldLength.ToString() :
+											String.Empty) + "}";
+
+			if (IsNumericType(Value))
+			{
+				w = Convert.ToString(UnboxToLong(Value, true), 8);
+
+				if (Left2Right || Padding == ' ')
+				{
+					if (Alternate && w != "0")
+						w = "0" + w;
+					w = String.Format(lengthFormat, w);
+				}
+				else
+				{
+					if (FieldLength != int.MinValue)
+						w = w.PadLeft(FieldLength - (Alternate && w != "0" ? 1 : 0), Padding);
+					if (Alternate && w != "0")
+						w = "0" + w;
+				}
+			}
+
+			return w;
+		}
+		#endregion
+		#region FormatHEX
+		private static string FormatHex(string NativeFormat, bool Alternate,
+											int FieldLength, int FieldPrecision,
+											bool Left2Right,
+											char Padding, object Value)
+		{
+			string w = String.Empty;
+			string lengthFormat = "{0" + (FieldLength != int.MinValue ?
+											"," + (Left2Right ?
+													"-" :
+													String.Empty) + FieldLength.ToString() :
+											String.Empty) + "}";
+			string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ?
+											FieldPrecision.ToString() :
+											String.Empty) + "}";
+
+			if (IsNumericType(Value))
+			{
+				w = String.Format(numberFormat, Value);
+
+				if (Left2Right || Padding == ' ')
+				{
+					if (Alternate)
+						w = (NativeFormat == "x" ? "0x" : "0X") + w;
+					w = String.Format(lengthFormat, w);
+				}
+				else
+				{
+					if (FieldLength != int.MinValue)
+						w = w.PadLeft(FieldLength - (Alternate ? 2 : 0), Padding);
+					if (Alternate)
+						w = (NativeFormat == "x" ? "0x" : "0X") + w;
+				}
+			}
+
+			return w;
+		}
+		#endregion
+		#region FormatNumber
+		private static string FormatNumber(string NativeFormat, bool Alternate,
+											int FieldLength, int FieldPrecision,
+											bool Left2Right,
+											bool PositiveSign, bool PositiveSpace,
+											char Padding, object Value)
+		{
+			string w = String.Empty;
+			string lengthFormat = "{0" + (FieldLength != int.MinValue ?
+											"," + (Left2Right ?
+													"-" :
+													String.Empty) + FieldLength.ToString() :
+											String.Empty) + "}";
+			string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ?
+											FieldPrecision.ToString() :
+											"0") + "}";
+
+			if (IsNumericType(Value))
+			{
+				w = String.Format(CultureInfo.InvariantCulture, numberFormat, Value);
+
+				if (Left2Right || Padding == ' ')
+				{
+					if (IsPositive(Value, true))
+						w = (PositiveSign ?
+								"+" : (PositiveSpace ? " " : String.Empty)) + w;
+					w = String.Format(lengthFormat, w);
+				}
+				else
+				{
+					if (w.StartsWith("-"))
+						w = w.Substring(1);
+					if (FieldLength != int.MinValue)
+						w = w.PadLeft(FieldLength - 1, Padding);
+					if (IsPositive(Value, true))
+						w = (PositiveSign ?
+								"+" : (PositiveSpace ?
+										" " : (FieldLength != int.MinValue ?
+												Padding.ToString() : String.Empty))) + w;
+					else
+						w = "-" + w;
+				}
+			}
+
+			return w;
+		}
+		#endregion
+		#endregion
+	}
+}
+
+

+ 24 - 2
src/MoonSharp.Interpreter/DataTypes/UserData.cs

@@ -18,7 +18,11 @@ namespace MoonSharp.Interpreter
 		public object Object { get; set; }
 		public object Object { get; set; }
 		internal UserDataDescriptor Descriptor { get; set; }
 		internal UserDataDescriptor Descriptor { get; set; }
 
 
+#if USE_RW_LOCK
 		private static ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
 		private static ReaderWriterLockSlim m_Lock = new ReaderWriterLockSlim();
+#else
+		private static object m_Lock = new object();
+#endif
 		private static Dictionary<Type, UserDataDescriptor> s_Registry = new Dictionary<Type, UserDataDescriptor>();
 		private static Dictionary<Type, UserDataDescriptor> s_Registry = new Dictionary<Type, UserDataDescriptor>();
 		private static InteropAccessMode m_DefaultAccessMode;
 		private static InteropAccessMode m_DefaultAccessMode;
 
 
@@ -115,7 +119,11 @@ namespace MoonSharp.Interpreter
 			if (accessMode == InteropAccessMode.Default)
 			if (accessMode == InteropAccessMode.Default)
 				accessMode = m_DefaultAccessMode;
 				accessMode = m_DefaultAccessMode;
 
 
+#if USE_RW_LOCK
 			m_Lock.EnterWriteLock();
 			m_Lock.EnterWriteLock();
+#else
+			Monitor.Enter(m_Lock);
+#endif
 
 
 			try
 			try
 			{
 			{
@@ -132,7 +140,11 @@ namespace MoonSharp.Interpreter
 			}
 			}
 			finally
 			finally
 			{
 			{
+#if USE_RW_LOCK
 				m_Lock.ExitWriteLock();
 				m_Lock.ExitWriteLock();
+#else
+				Monitor.Exit(m_Lock);
+#endif
 			}
 			}
 		}
 		}
 
 
@@ -143,7 +155,11 @@ namespace MoonSharp.Interpreter
 
 
 		private static UserDataDescriptor GetDescriptorForType(Type type, bool deepSearch = true)
 		private static UserDataDescriptor GetDescriptorForType(Type type, bool deepSearch = true)
 		{
 		{
+#if USE_RW_LOCK
 			m_Lock.EnterReadLock();
 			m_Lock.EnterReadLock();
+#else
+			Monitor.Enter(m_Lock);
+#endif
 
 
 			try
 			try
 			{
 			{
@@ -152,8 +168,10 @@ namespace MoonSharp.Interpreter
 
 
 				for (Type t = type; t != typeof(object); t = t.BaseType)
 				for (Type t = type; t != typeof(object); t = t.BaseType)
 				{
 				{
-					if (s_Registry.ContainsKey(t))
-						return s_Registry[t];
+					UserDataDescriptor u;
+
+					if (s_Registry.TryGetValue(t, out u))
+						return u;
 				}
 				}
 
 
 				foreach (Type t in type.GetInterfaces())
 				foreach (Type t in type.GetInterfaces())
@@ -167,7 +185,11 @@ namespace MoonSharp.Interpreter
 			}
 			}
 			finally
 			finally
 			{
 			{
+#if USE_RW_LOCK
 				m_Lock.ExitReadLock();
 				m_Lock.ExitReadLock();
+#else
+				Monitor.Exit(m_Lock);
+#endif
 			}
 			}
 
 
 			return null;
 			return null;

+ 40 - 0
src/MoonSharp.Interpreter/Diagnostics/PerformanceCounters/DummyPerformanceStopwatch.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Diagnostics.PerformanceCounters
+{
+	class DummyPerformanceStopwatch : IPerformanceStopwatch, IDisposable
+	{
+		public static DummyPerformanceStopwatch Instance = new DummyPerformanceStopwatch();
+		PerformanceResult m_Result;
+
+		private DummyPerformanceStopwatch()
+		{
+			m_Result = new PerformanceResult()
+			{
+				Counter = 0,
+				Global = true,
+				Instances = 0,
+				Name = "::dummy::",
+				Type = PerformanceCounterType.TimeMilliseconds
+			};
+		}
+
+
+		public IDisposable Start()
+		{
+			return this;
+		}
+
+		public PerformanceResult GetResult()
+		{
+			return m_Result;
+		}
+
+		public void Dispose()
+		{
+		}
+	}
+}

+ 39 - 11
src/MoonSharp.Interpreter/Diagnostics/PerformanceStatistics.cs

@@ -13,18 +13,39 @@ namespace MoonSharp.Interpreter.Diagnostics
 	{
 	{
 		IPerformanceStopwatch[] m_Stopwatches = new IPerformanceStopwatch[(int)PerformanceCounter.LastValue];
 		IPerformanceStopwatch[] m_Stopwatches = new IPerformanceStopwatch[(int)PerformanceCounter.LastValue];
 		static IPerformanceStopwatch[] m_GlobalStopwatches = new IPerformanceStopwatch[(int)PerformanceCounter.LastValue];
 		static IPerformanceStopwatch[] m_GlobalStopwatches = new IPerformanceStopwatch[(int)PerformanceCounter.LastValue];
+		bool m_Enabled = false;
 
 
-		static PerformanceStatistics()
-		{
-			m_GlobalStopwatches[(int)PerformanceCounter.AdaptersCompilation] = new GlobalPerformanceStopwatch(PerformanceCounter.AdaptersCompilation);
-		}
 
 
-		internal PerformanceStatistics()
+		/// <summary>
+		/// Gets or sets a value indicating whether this collection of performance stats is enabled.
+		/// </summary>
+		/// <value>
+		///   <c>true</c> if enabled; otherwise, <c>false</c>.
+		/// </value>
+		public bool Enabled
 		{
 		{
-			for (int i = 0; i < (int)PerformanceCounter.LastValue; i++)
-				m_Stopwatches[i] = m_GlobalStopwatches[i] ?? new PerformanceStopwatch((PerformanceCounter)i);
+			get { return m_Enabled; }
+			set
+			{
+				if (value && !m_Enabled)
+				{
+					if (m_GlobalStopwatches[(int)PerformanceCounter.AdaptersCompilation] == null)
+						m_GlobalStopwatches[(int)PerformanceCounter.AdaptersCompilation] = new GlobalPerformanceStopwatch(PerformanceCounter.AdaptersCompilation);
+
+					for (int i = 0; i < (int)PerformanceCounter.LastValue; i++)
+						m_Stopwatches[i] = m_GlobalStopwatches[i] ?? new PerformanceStopwatch((PerformanceCounter)i);
+				}
+				else if (!value && m_Enabled)
+				{
+					m_Stopwatches = new IPerformanceStopwatch[(int)PerformanceCounter.LastValue];
+					m_GlobalStopwatches = new IPerformanceStopwatch[(int)PerformanceCounter.LastValue];
+				}
+
+				m_Enabled = value;
+			}
 		}
 		}
 
 
+
 		/// <summary>
 		/// <summary>
 		/// Gets the result of the specified performance counter .
 		/// Gets the result of the specified performance counter .
 		/// </summary>
 		/// </summary>
@@ -32,7 +53,8 @@ namespace MoonSharp.Interpreter.Diagnostics
 		/// <returns></returns>
 		/// <returns></returns>
 		public PerformanceResult GetPerformanceCounterResult(PerformanceCounter pc)
 		public PerformanceResult GetPerformanceCounterResult(PerformanceCounter pc)
 		{
 		{
-			return m_Stopwatches[(int)pc].GetResult();
+			var pco = m_Stopwatches[(int)pc];
+			return (pco != null) ? pco.GetResult() : null;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -41,7 +63,8 @@ namespace MoonSharp.Interpreter.Diagnostics
 		/// <returns></returns>
 		/// <returns></returns>
 		internal IDisposable StartStopwatch(PerformanceCounter pc)
 		internal IDisposable StartStopwatch(PerformanceCounter pc)
 		{
 		{
-			return m_Stopwatches[(int)pc].Start();
+			var pco = m_Stopwatches[(int)pc];
+			return (pco != null) ? pco.Start() : null;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -50,7 +73,8 @@ namespace MoonSharp.Interpreter.Diagnostics
 		/// <returns></returns>
 		/// <returns></returns>
 		internal static IDisposable StartGlobalStopwatch(PerformanceCounter pc)
 		internal static IDisposable StartGlobalStopwatch(PerformanceCounter pc)
 		{
 		{
-			return m_GlobalStopwatches[(int)pc].Start();
+			var pco = m_GlobalStopwatches[(int)pc];
+			return (pco != null) ? pco.Start() : null;
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>
@@ -62,7 +86,11 @@ namespace MoonSharp.Interpreter.Diagnostics
 			StringBuilder sb = new StringBuilder();
 			StringBuilder sb = new StringBuilder();
 
 
 			for (int i = 0; i < (int)PerformanceCounter.LastValue; i++)
 			for (int i = 0; i < (int)PerformanceCounter.LastValue; i++)
-				sb.AppendLine(this.GetPerformanceCounterResult((PerformanceCounter)i).ToString());
+			{
+				var res = this.GetPerformanceCounterResult((PerformanceCounter)i);
+				if (res != null)
+					sb.AppendLine(res.ToString());
+			}
 
 
 			return sb.ToString();
 			return sb.ToString();
 		}
 		}

+ 8 - 7
src/MoonSharp.Interpreter/Interop/ConversionHelper.cs

@@ -9,7 +9,7 @@ namespace MoonSharp.Interpreter.Interop
 {
 {
 	internal static class ConversionHelper
 	internal static class ConversionHelper
 	{
 	{
-		static readonly Type[] NumericTypes = 
+		static readonly HashSet<Type> NumericTypes = new HashSet<Type>()
 		{
 		{
 			typeof(sbyte), 
 			typeof(sbyte), 
 			typeof(byte), 
 			typeof(byte), 
@@ -24,6 +24,7 @@ namespace MoonSharp.Interpreter.Interop
 			typeof(double)
 			typeof(double)
 		};
 		};
 
 
+
 		internal static bool CheckCallbackSignature(MethodInfo mi)
 		internal static bool CheckCallbackSignature(MethodInfo mi)
 		{
 		{
 			ParameterInfo[] pi = mi.GetParameters();
 			ParameterInfo[] pi = mi.GetParameters();
@@ -42,15 +43,18 @@ namespace MoonSharp.Interpreter.Interop
 
 
 			Type t = obj.GetType();
 			Type t = obj.GetType();
 
 
-			if (NumericTypes.Contains(t))
-				return DynValue.NewNumber(TypeToDouble(t, obj));
-
 			if (obj is bool)
 			if (obj is bool)
 				return DynValue.NewBoolean((bool)obj);
 				return DynValue.NewBoolean((bool)obj);
 
 
 			if (obj is string || obj is StringBuilder || obj is char)
 			if (obj is string || obj is StringBuilder || obj is char)
 				return DynValue.NewString(obj.ToString());
 				return DynValue.NewString(obj.ToString());
 
 
+			if (obj is Closure)
+				return DynValue.NewClosure((Closure)obj);
+
+			if (NumericTypes.Contains(t))
+				return DynValue.NewNumber(TypeToDouble(t, obj));
+
 			if (obj is Table)
 			if (obj is Table)
 				return DynValue.NewTable((Table)obj);
 				return DynValue.NewTable((Table)obj);
 
 
@@ -85,9 +89,6 @@ namespace MoonSharp.Interpreter.Interop
 
 
 			if (v != null) return v;
 			if (v != null) return v;
 
 
-			if (obj is Closure)
-				return DynValue.NewClosure((Closure)obj);
-
 			if (obj is Delegate)
 			if (obj is Delegate)
 				return DynValue.NewCallback(CallbackFunction.FromDelegate(script, (Delegate)obj));
 				return DynValue.NewCallback(CallbackFunction.FromDelegate(script, (Delegate)obj));
 
 

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

@@ -3,7 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
 
 
-namespace MoonSharp.Interpreter.Interop
+namespace MoonSharp.Interpreter
 {
 {
 	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
 	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
 	public sealed class MoonSharpUserDataAttribute : Attribute
 	public sealed class MoonSharpUserDataAttribute : Attribute

+ 13 - 9
src/MoonSharp.Interpreter/Interop/UserDataDescriptor.cs

@@ -66,14 +66,16 @@ namespace MoonSharp.Interpreter.Interop
 
 
 		internal DynValue Index(Script script, object obj, string idxname)
 		internal DynValue Index(Script script, object obj, string idxname)
 		{
 		{
-			if (m_Methods.ContainsKey(idxname))
-			{
-				return DynValue.NewCallback(m_Methods[idxname].GetCallback(script, obj));
-			}
+			UserDataMethodDescriptor mdesc;
+
+			if (m_Methods.TryGetValue(idxname, out mdesc))
+				return DynValue.NewCallback(mdesc.GetCallback(script, obj));
 
 
-			if (m_Properties.ContainsKey(idxname))
+			UserDataPropertyDescriptor pdesc;
+
+			if (m_Properties.TryGetValue(idxname, out pdesc))
 			{
 			{
-				object o = m_Properties[idxname].GetValue(obj);
+				object o = pdesc.GetValue(obj);
 				return ConversionHelper.ClrObjectToComplexMoonSharpValue(script, o);
 				return ConversionHelper.ClrObjectToComplexMoonSharpValue(script, o);
 			}
 			}
 
 
@@ -82,10 +84,12 @@ namespace MoonSharp.Interpreter.Interop
 
 
 		internal void SetIndex(Script script, object obj, string idxname, DynValue value)
 		internal void SetIndex(Script script, object obj, string idxname, DynValue value)
 		{
 		{
-			if (m_Properties.ContainsKey(idxname))
+			UserDataPropertyDescriptor pdesc;
+
+			if (m_Properties.TryGetValue(idxname, out pdesc))
 			{
 			{
-				object o = ConversionHelper.MoonSharpValueToObjectOfType(value, m_Properties[idxname].PropertyInfo.PropertyType, null);
-				m_Properties[idxname].SetValue(obj, o, value.Type);
+				object o = ConversionHelper.MoonSharpValueToObjectOfType(value, pdesc.PropertyInfo.PropertyType, null);
+				pdesc.SetValue(obj, o, value.Type);
 			}
 			}
 			else
 			else
 			{
 			{

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

@@ -30,7 +30,7 @@ namespace MoonSharp.Interpreter.Interop
 			this.IsStatic = mi.IsStatic;
 			this.IsStatic = mi.IsStatic;
 
 
 			m_Arguments = mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
 			m_Arguments = mi.GetParameters().Select(pi => pi.ParameterType).ToArray();
-			m_Defaults = mi.GetParameters().Select(pi => pi.DefaultValue).ToArray();
+			m_Defaults = mi.GetParameters().Select(pi => pi.DefaultValue).ToArray(); 
 
 
 			if (AccessMode == InteropAccessMode.Preoptimized)
 			if (AccessMode == InteropAccessMode.Preoptimized)
 				Optimize();
 				Optimize();
@@ -72,11 +72,17 @@ namespace MoonSharp.Interpreter.Interop
 			object retv = null;
 			object retv = null;
 
 
 			if (m_OptimizedFunc != null)
 			if (m_OptimizedFunc != null)
+			{
 				retv = m_OptimizedFunc(obj, pars);
 				retv = m_OptimizedFunc(obj, pars);
+			}
 			else if (m_OptimizedAction != null)
 			else if (m_OptimizedAction != null)
+			{
 				m_OptimizedAction(obj, pars);
 				m_OptimizedAction(obj, pars);
+			}
 			else
 			else
+			{
 				retv = MethodInfo.Invoke(obj, pars);
 				retv = MethodInfo.Invoke(obj, pars);
+			}
 
 
 			return ConversionHelper.ClrObjectToComplexMoonSharpValue(script, retv);
 			return ConversionHelper.ClrObjectToComplexMoonSharpValue(script, retv);
 		}
 		}

+ 6 - 2
src/MoonSharp.Interpreter/Modules/CoreModules.cs

@@ -21,12 +21,16 @@ namespace MoonSharp.Interpreter
 		Math = 0x100,
 		Math = 0x100,
 		Coroutine = 0x200,
 		Coroutine = 0x200,
 		Bit32 = 0x400,
 		Bit32 = 0x400,
+		Os_Time = 0x800,
+		Os_System = 0x1000,
+		File = 0x2000,
+		Io = 0x4000,
 
 
 
 
 
 
 		Preset_HardSandbox = GlobalConsts | TableIterators | String | Table | Basic | Math | Bit32,
 		Preset_HardSandbox = GlobalConsts | TableIterators | String | Table | Basic | Math | Bit32,
-		Preset_SoftSandbox = Preset_HardSandbox | Metatables | ErrorHandling | Coroutine,
-		Preset_Default = Preset_SoftSandbox | LoadMethods,
+		Preset_SoftSandbox = Preset_HardSandbox | Metatables | ErrorHandling | Coroutine | Os_Time,
+		Preset_Default = Preset_SoftSandbox | LoadMethods | Os_System | File | Io,
 		Preset_Complete = Preset_Default,
 		Preset_Complete = Preset_Default,
 
 
 	}
 	}

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

@@ -85,6 +85,7 @@
     <Compile Include="CoreLib\Bit32Module.cs" />
     <Compile Include="CoreLib\Bit32Module.cs" />
     <Compile Include="CoreLib\MathModule.cs" />
     <Compile Include="CoreLib\MathModule.cs" />
     <Compile Include="CoreLib\MetaTableMethods.cs" />
     <Compile Include="CoreLib\MetaTableMethods.cs" />
+    <Compile Include="CoreLib\OsMethods.cs" />
     <Compile Include="CoreLib\Patterns\CaptureInfo.cs">
     <Compile Include="CoreLib\Patterns\CaptureInfo.cs">
       <SubType>Code</SubType>
       <SubType>Code</SubType>
     </Compile>
     </Compile>
@@ -95,6 +96,7 @@
       <SubType>Code</SubType>
       <SubType>Code</SubType>
     </Compile>
     </Compile>
     <Compile Include="CoreLib\Patterns\StringRange.cs" />
     <Compile Include="CoreLib\Patterns\StringRange.cs" />
+    <Compile Include="CoreLib\Patterns\Tools.cs" />
     <Compile Include="CoreLib\StringModule.cs" />
     <Compile Include="CoreLib\StringModule.cs" />
     <Compile Include="CoreLib\TableIterators.cs" />
     <Compile Include="CoreLib\TableIterators.cs" />
     <Compile Include="CoreLib\TableModule.cs" />
     <Compile Include="CoreLib\TableModule.cs" />
@@ -118,6 +120,7 @@
     <Compile Include="Debugging\SourceRef.cs" />
     <Compile Include="Debugging\SourceRef.cs" />
     <Compile Include="Debugging\WatchItem.cs" />
     <Compile Include="Debugging\WatchItem.cs" />
     <Compile Include="Debugging\WatchType.cs" />
     <Compile Include="Debugging\WatchType.cs" />
+    <Compile Include="Diagnostics\PerformanceCounters\DummyPerformanceStopwatch.cs" />
     <Compile Include="Diagnostics\PerformanceCounters\IPerformanceStopwatch.cs" />
     <Compile Include="Diagnostics\PerformanceCounters\IPerformanceStopwatch.cs" />
     <Compile Include="Diagnostics\PerformanceCounter.cs" />
     <Compile Include="Diagnostics\PerformanceCounter.cs" />
     <Compile Include="Diagnostics\PerformanceCounters\GlobalPerformanceStopwatch.cs" />
     <Compile Include="Diagnostics\PerformanceCounters\GlobalPerformanceStopwatch.cs" />

+ 1 - 1
src/MoonSharp.Interpreter/Properties/AssemblyInfo.cs

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
 // You can specify all the values or you can default the Build and Revision Numbers 
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.5.5.0")]
+[assembly: AssemblyVersion("0.5.6.0")]
 [assembly: AssemblyFileVersion("1.0.0.0")]
 [assembly: AssemblyFileVersion("1.0.0.0")]

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

@@ -292,7 +292,12 @@ namespace MoonSharp.Interpreter
 			if (function.Type != DataType.Function)
 			if (function.Type != DataType.Function)
 				throw new ArgumentException("function is not of DataType.Function");
 				throw new ArgumentException("function is not of DataType.Function");
 
 
-			return m_MainProcessor.Call(function, args.Select(v => DynValue.FromObject(this, v)).ToArray());
+			DynValue[] dargs = new DynValue[args.Length];
+
+			for (int i = 0; i < dargs.Length; i++)
+				dargs[i] = DynValue.FromObject(this, args[i]);
+
+			return m_MainProcessor.Call(function, dargs);
 		}
 		}
 
 
 		/// <summary>
 		/// <summary>

+ 7 - 2
src/MoonSharpTests/MoonSharpTests.csproj

@@ -9,9 +9,10 @@
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>MoonSharpTests</RootNamespace>
     <RootNamespace>MoonSharpTests</RootNamespace>
     <AssemblyName>MoonSharpTests</AssemblyName>
     <AssemblyName>MoonSharpTests</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <FileAlignment>512</FileAlignment>
-    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -22,6 +23,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -31,6 +33,7 @@
     <DefineConstants>TRACE</DefineConstants>
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
@@ -40,6 +43,7 @@
     <PlatformTarget>x86</PlatformTarget>
     <PlatformTarget>x86</PlatformTarget>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
     <OutputPath>bin\x86\Release\</OutputPath>
     <OutputPath>bin\x86\Release\</OutputPath>
@@ -49,6 +53,7 @@
     <PlatformTarget>x86</PlatformTarget>
     <PlatformTarget>x86</PlatformTarget>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
     <Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">

+ 1 - 1
src/MoonSharpTests/app.config

@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
 <configuration>
-<startup><supportedRuntime version="v2.0.50727" sku="Client"/></startup></configuration>
+<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/></startup></configuration>

+ 87 - 0
src/PerformanceComparison/CallbacksAndForthTests.cs

@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using MoonSharp.Interpreter;
+using NLua;
+
+namespace PerformanceComparison
+{
+	[MoonSharpUserData]
+	public class ChampionPropertiesComponent
+	{
+		string name;
+
+		internal void SetFirstName(string p)
+		{
+			name = p;
+		}
+
+		internal void SetLastName(string p)
+		{
+			name += " " + p;
+		}
+
+		public string getName()
+		{
+			return name;
+		}
+
+		internal ChampionPropertiesComponent ToInterface()
+		{
+			return this;
+		}
+	}
+
+
+	class CallbacksAndForthTests
+	{
+		public static void Main()
+		{
+			(new CallbacksAndForthTests()).Start();
+			//Console.ReadLine();
+		}
+
+		private void Start()
+		{
+			//UserData.DefaultAccessMode = InteropAccessMode.Preoptimized;
+			UserData.RegisterAssembly();
+
+			//var nLuaState = new Lua();
+			var moonSharpState = new Script();
+
+			const string script = @"
+			a = """"
+			onUpdate = function(championPropertiesComponent)
+				a = championPropertiesComponent:getName()
+			end
+		"; 
+
+			//nLuaState.DoString(script);
+			moonSharpState.DoString(script);
+
+			var championProperties = new ChampionPropertiesComponent();
+			championProperties.SetFirstName("John");
+			championProperties.SetLastName("Smith");
+
+			//var nLuaFunction = (LuaFunction)nLuaState["onUpdate"];
+			var moonSharpFunction = (Closure)moonSharpState.Globals["onUpdate"];
+
+			int startTime, endTime;
+
+			//// Test NLua
+			//startTime = Environment.TickCount;
+			//for (int i = 0; i < 100000; i++) nLuaFunction.Call(championProperties.ToInterface());
+			//endTime = Environment.TickCount;
+			//Console.WriteLine("NLua : {0}", endTime - startTime);
+
+			// Test MoonSharp
+			startTime = Environment.TickCount;
+			//DynValue v = DynValue.FromObject(moonSharpState, championProperties.ToInterface());
+			for (int i = 0; i < 100000; i++) moonSharpFunction.Call(championProperties.ToInterface());
+			endTime = Environment.TickCount;
+			Console.WriteLine("MoonSharp : {0}", endTime - startTime);
+		}
+
+	}
+}

+ 1 - 1
src/PerformanceComparison/HugeFile.cs

@@ -10,7 +10,7 @@ namespace PerformanceComparison
 {
 {
 	public class HugeFile
 	public class HugeFile
 	{
 	{
-		static void Main(string[] args)
+		static void xxxxMain(string[] args)
 		{
 		{
 			Console.WriteLine("Started...");
 			Console.WriteLine("Started...");
 			Script.WarmUp();
 			Script.WarmUp();

+ 5 - 0
src/PerformanceComparison/PerformanceComparison.csproj

@@ -31,6 +31,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>0</WarningLevel>
     <WarningLevel>0</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -41,6 +42,7 @@
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
     <UseVSHostingProcess>false</UseVSHostingProcess>
     <UseVSHostingProcess>false</UseVSHostingProcess>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
@@ -50,6 +52,7 @@
     <PlatformTarget>x86</PlatformTarget>
     <PlatformTarget>x86</PlatformTarget>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
     <OutputPath>bin\x86\Release\</OutputPath>
     <OutputPath>bin\x86\Release\</OutputPath>
@@ -60,6 +63,7 @@
     <UseVSHostingProcess>false</UseVSHostingProcess>
     <UseVSHostingProcess>false</UseVSHostingProcess>
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="KeraLua">
     <Reference Include="KeraLua">
@@ -76,6 +80,7 @@
     <Reference Include="System.Xml" />
     <Reference Include="System.Xml" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
+    <Compile Include="CallbacksAndForthTests.cs" />
     <Compile Include="HugeFile.cs" />
     <Compile Include="HugeFile.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Program.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />

+ 3 - 0
src/moonsharp.sln

@@ -86,4 +86,7 @@ Global
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE
 	EndGlobalSection
 	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
 EndGlobal
 EndGlobal