@@ -11,916 +11,919 @@
  * You must not remove this notice, or any other, from this software.
  *
  *
- * ***************************************************************************/
-
-#if FEATURE_CORE_DLR
-using System.Linq.Expressions;
+ * ***************************************************************************/
+
+#if FEATURE_CORE_DLR
+using System.Linq.Expressions;
 #else
 using Microsoft.Scripting.Ast;
-#endif
-
-using System;
-using System.Globalization;
-using System.Diagnostics;
-using System.Text;
-using System.Reflection;
-using System.Collections;
-using System.Collections.Generic;
-using System.Dynamic;
-using Microsoft.Scripting.Utils;
-using IronRuby.Builtins;
-using Microsoft.Scripting;
-
-namespace IronRuby.Runtime {
-    public static class Utils {
-        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
-        public static readonly byte[] EmptyBytes = new byte[0];
-
-        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
-        public static readonly char[] EmptyChars = new char[0];
-        
-        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
-        public static readonly MemberInfo[] EmptyMemberInfos = new MemberInfo[0];
-
-        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
-        public static readonly Delegate[] EmptyDelegates = new Delegate[0];
-
-        public static int IndexOf(this string[]/*!*/ array, string/*!*/ value, StringComparer/*!*/ comparer) {
-            ContractUtils.RequiresNotNull(array, "array");
-            ContractUtils.RequiresNotNull(value, "value");
-            ContractUtils.RequiresNotNull(comparer, "comparer");
-
-            for (int i = 0; i < array.Length; i++) {
-                if (comparer.Equals(array[i], value)) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        public static bool IsAscii(this string/*!*/ str) {
-            for (int i = 0; i < str.Length; i++) {
-                if (str[i] > 0x7f) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public static bool IsAscii(this byte[]/*!*/ bytes, int count) {
-            for (int i = 0; i < count; i++) {
-                if (bytes[i] > 0x7f) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public static bool IsAscii(this char[]/*!*/ str, int count) {
-            for (int i = 0; i < count; i++) {
-                if (str[i] > 0x7f) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public static bool IsAscii(this char[]/*!*/ str, int start, int count) {
-            for (int i = 0; i < count; i++) {
-                if (str[start + i] > 0x7f) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        internal static bool IsBinary(this string/*!*/ str) {
-            for (int i = 0; i < str.Length; i++) {
-                if (str[i] > 0xff) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        internal static int GetCharacterCount(this string/*!*/ str) {
-            int surrogateCount = 0;
-            bool wasHighSurrogate = false;
-            for (int i = 0; i < str.Length; i++) {
-                char c = str[i];
-                if (c >= '\uD800') {
-                    if (c <= '\uDBFF') {
-                        wasHighSurrogate = true;
-                    } else if (wasHighSurrogate && c <= '\uDFFF') {
-                        surrogateCount++;
-                        wasHighSurrogate = false;
-                    }
-                }
-            }
-            return str.Length - surrogateCount;
-        }
-
-        /// <summary>
-        /// Calculates the number of Unicode characters in given array.
-        /// Assumes that the content of the array beyond count chars doesn't contain significant data and can be overwritten.
-        /// </summary>
-        internal static int GetCharacterCount(this char[]/*!*/ str, int count) {
-            int surrogateCount = 0;
-            bool wasHighSurrogate = false;
-            if (count < str.Length) {
-                str[count] = '\uffff';
-            }
-
-            for (int i = 0; i < str.Length; i++) {
-                char c = str[i];
-                if (c >= '\uD800') {
-                    if (i >= count) {
-                        break;
-                    } else if (c <= '\uDBFF') {
-                        wasHighSurrogate = true;
-                    } else if (wasHighSurrogate && c <= '\uDFFF') {
-                        surrogateCount++;
-                        wasHighSurrogate = false;
-                    }
-                }
-            }
-            return str.Length - surrogateCount;
-        }
-
-        public static string/*!*/ ToAsciiString(this string/*!*/ str) {
-            return MutableString.AppendUnicodeRepresentation(new StringBuilder(), str, MutableString.Escape.NonAscii, -1, -1).ToString();
-        }
-
-        public static int LastCharacter(this string/*!*/ str) {
-            return str.Length == 0 ? -1 : str[str.Length - 1];
-        }
-
-        internal static IEnumerable<byte>/*!*/ EnumerateAsBytes(char[]/*!*/ data, int count) {
-            for (int i = 0; i < count; i++) {
-                yield return (byte)data[i];
-            }
-        }
-
-        internal static IEnumerable<byte>/*!*/ EnumerateAsBytes(string/*!*/ data) {
-            for (int i = 0; i < data.Length; i++) {
-                yield return (byte)data[i];
-            }
-        }
-
-        internal static IEnumerable<T>/*!*/ Enumerate<T>(T[]/*!*/ data, int count) {
-            for (int i = 0; i < count; i++) {
-                yield return data[i];
-            }
-        }
-
-        internal const int MinListSize = 4;
-        internal const int MinBufferSize = 16;
-
-        internal static int GetExpandedSize<T>(T[]/*!*/ array, int minLength) {
-            return Math.Max(minLength, Math.Max(1 + (array.Length << 1), typeof(T) == typeof(object) ? MinListSize : MinBufferSize));
-        }
-
-        internal static void Resize<T>(ref T[]/*!*/ array, int minLength) {
-            if (array.Length < minLength) {
-                Array.Resize(ref array, GetExpandedSize(array, minLength));
-            }
-        }
-
-        internal static void TrimExcess<T>(ref T[] data, int count) {
-            if (IsSparse(count, data.Length)) {
-                Array.Resize(ref data, count);
-            }
-        }
-
-        internal static bool IsSparse(int portionSize, int totalSize) {
-            Debug.Assert(portionSize <= totalSize);
-            return (long)portionSize * 10 < (long)totalSize * 9;
-        }
-
-        internal static void ResizeForInsertion<T>(ref T[]/*!*/ array, int itemCount, int index, int count) {
-            int minLength = itemCount + count;
-            T[] a;
-            if (array.Length < minLength) {
-                a = new T[GetExpandedSize(array, minLength)];
-                Array.Copy(array, 0, a, 0, index);
-            } else {
-                a = array;
-            }
-
-            Array.Copy(array, index, a, index + count, itemCount - index);
-            array = a;
-        }
-
-        internal static void Fill<T>(T[]/*!*/ array, int index, T item, int repeatCount) {
-            // TODO: can be optimized for big repeatCount:
-            for (int i = index; i < index + repeatCount; i++) {
-                array[i] = item;
-            }
-        }
-
-        private static void Fill(byte[]/*!*/ src, int srcStart, byte[]/*!*/ dst, int dstStart, int count, int repeatCount) {
-            // TODO: can be optimized for big repeatCount or big count:
-            if (count == 1) {
-                Fill(dst, dstStart, src[srcStart], repeatCount);
-            } else {
-                for (int i = 0; i < repeatCount; i++) {
-                    for (int j = 0; j < count; j++) {
-                        dst[dstStart++] = src[srcStart + j];
-                    }
-                }
-            }
-        }
-
-        private static int GetByteCount(string/*!*/ str, int start, int count, Encoding/*!*/ encoding, out char[]/*!*/ chars) {
-            // TODO: we can special case this for some encodings and calculate the byte count w/o copying the content: 
-            chars = new char[count];
-            str.CopyTo(start, chars, 0, count);
-            return encoding.GetByteCount(chars, 0, chars.Length);
-        }
-
-        internal static T[]/*!*/ Concatenate<T>(T[]/*!*/ array1, T[]/*!*/ array2) {
-            return Concatenate(array1, array1.Length, array2, array2.Length);
-        }
-
-        internal static T[]/*!*/ Concatenate<T>(params T[][] arrays) {
-            int length = 0;
-            foreach (var array in arrays) {
-                length += array.Length;
-            }
-
-            T[] result = new T[length];
-            length = 0;
-            foreach (var array in arrays) {
-                Array.Copy(array, 0, result, length, array.Length);
-                length += array.Length;
-            }
-            return result;
-        }
-
-        internal static T[]/*!*/ Concatenate<T>(T[]/*!*/ array1, int itemCount1, T[]/*!*/ array2, int itemCount2) {
-            T[] result = new T[itemCount1 + itemCount2];
-            Array.Copy(array1, 0, result, 0, itemCount1);
-            Array.Copy(array2, 0, result, itemCount1, itemCount2);
-            return result;
-        }
-
-        internal static int Append<T>(ref T[]/*!*/ array, int itemCount, T item, int repeatCount) {
-            Resize(ref array, itemCount + repeatCount);
-            Fill(array, itemCount, item, repeatCount);
-            return itemCount + repeatCount;
-        }
-
-        internal static int Append(ref char[]/*!*/ array, int itemCount, string/*!*/ other, int start, int count) {
-            int newCount = itemCount + count;
-            Resize(ref array, newCount);
-            other.CopyTo(start, array, itemCount, count);
-            return newCount;
-        }
-
-        internal static int Append<T>(ref T[]/*!*/ array, int itemCount, T[]/*!*/ other, int start, int count) {
-            int newCount = itemCount + count;
-            Resize(ref array, newCount);
-            Array.Copy(other, start, array, itemCount, count);
-            return newCount;
-        }
-
-        internal static int Append(ref byte[]/*!*/ array, int itemCount, string/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
-            char[] appendChars;
-            int newCount = itemCount + GetByteCount(other, start, count, encoding, out appendChars);
-            Resize(ref array, newCount);
-            encoding.GetBytes(appendChars, 0, appendChars.Length, array, itemCount);
-            return newCount;
-        }
-
-        internal static int Append(ref byte[]/*!*/ array, int itemCount, char[]/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
-            int newCount = itemCount + encoding.GetByteCount(other, start, count);
-            Resize(ref array, newCount);
-            encoding.GetBytes(other, start, count, array, itemCount);
-            return newCount;
-        }
-
-        internal static int Append(ref byte[]/*!*/ array, int itemCount, char other, int repeatCount, Encoding/*!*/ encoding) {
-            if (repeatCount == 0) {
-                return itemCount;
-            }
-
-            char[] chars = new char[] { other };
-            int charSize = encoding.GetByteCount(chars, 0, 1);
-            int newCount = itemCount + charSize * repeatCount;
-            Resize(ref array, newCount);
-
-            encoding.GetBytes(chars, 0, 1, array, itemCount);
-            Fill(array, itemCount, array, itemCount + charSize, charSize, repeatCount - 1);
-            
-            return newCount;
-        }
-
-        internal static int InsertAt<T>(ref T[]/*!*/ array, int itemCount, int index, T other, int repeatCount) {
-            ResizeForInsertion(ref array, itemCount, index, repeatCount);
-            Fill(array, index, other, repeatCount);
-            return itemCount + repeatCount;
-        }
-
-        internal static int InsertAt(ref char[]/*!*/ array, int itemCount, int index, string/*!*/ other, int start, int count) {
-            ResizeForInsertion(ref array, itemCount, index, count);
-            other.CopyTo(start, array, index, count);
-            return itemCount + count;
-        }
-
-        internal static int InsertAt<T>(ref T[]/*!*/ array, int itemCount, int index, T[]/*!*/ other, int start, int count) {
-            ResizeForInsertion(ref array, itemCount, index, count);
-            Array.Copy(other, start, array, index, count);
-            return itemCount + count;
-        }
-
-        internal static int InsertAt(ref byte[]/*!*/ array, int itemCount, int index, string/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
-            char[] insertChars;
-            int insertedCount = GetByteCount(other, start, count, encoding, out insertChars);
-            ResizeForInsertion(ref array, itemCount, index, insertedCount);
-            encoding.GetBytes(insertChars, 0, insertChars.Length, array, itemCount);
-            return itemCount + insertedCount;
-        }
-
-        internal static int InsertAt(ref byte[]/*!*/ array, int itemCount, int index, char[]/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
-            int insertedCount = encoding.GetByteCount(other, start, count);
-            ResizeForInsertion(ref array, itemCount, index, insertedCount);
-            encoding.GetBytes(other, start, count, array, itemCount);
-            return itemCount + insertedCount;
-        }
-
-        internal static int InsertAt(ref byte[]/*!*/ array, int itemCount, int index, char other, int repeatCount, Encoding/*!*/ encoding) {
-            if (repeatCount == 0) {
-                return itemCount;
-            }
-
-            char[] chars = new char[] { other };
-            int charSize = encoding.GetByteCount(chars, 0, 1);
-            int insertedCount = charSize * repeatCount;
-
-            ResizeForInsertion(ref array, itemCount, index, insertedCount);
-
-            // first character:
-            encoding.GetBytes(chars, 0, 1, array, itemCount);
-            Fill(array, itemCount, array, itemCount + charSize, charSize, repeatCount - 1);
-            return itemCount + insertedCount;
-        }
-
-        internal static int Remove<T>(ref T[]/*!*/ array, int itemCount, int start, int count) {
-            T[] a;
-            int remaining = itemCount - count;
-            if (remaining > MinBufferSize && remaining < itemCount / 2) {
-                a = new T[remaining];
-                Array.Copy(array, 0, a, 0, start);
-            } else {
-                a = array;
-            }
-
-            Array.Copy(array, start + count, a, start, remaining - start);
-            array = a;
-            return remaining;
-        }
-
-        internal static T[]/*!*/ GetSlice<T>(this T[]/*!*/ array, int start, int count) {
-            var copy = new T[count];
-            Array.Copy(array, start, copy, 0, count);
-            return copy;
-        }
-
-        internal static T[]/*!*/ GetSlice<T>(this T[]/*!*/ array, int arrayLength, int start, int count) {
-            count = NormalizeCount(arrayLength, start, count);
-            var copy = new T[count];
-            if (count > 0) {
-                Array.Copy(array, start, copy, 0, count);
-            }
-            return copy;
-        }
-
-        internal static string/*!*/ GetSlice(this string/*!*/ str, int start, int count) {
-            count = NormalizeCount(str.Length, start, count);
-            return count > 0 ? str.Substring(start, count) : String.Empty;
-        }
-
-        internal static string/*!*/ GetStringSlice(this char[]/*!*/ chars, int arrayLength, int start, int count) {
-            count = NormalizeCount(arrayLength, start, count);
-            return count > 0 ? new String(chars, start, count) : String.Empty;
-        }
-
-        internal static int NormalizeCount(int arrayLength, int start, int count) {
-            if (count > arrayLength - start) {
-                return start >= arrayLength ? 0 : arrayLength - start;
-            } else {
-                return count;
-            }
-        }
-
-        internal static void NormalizeLastIndexOfIndices(int arrayLength, ref int start, ref int count) {
-            if (start >= arrayLength) {
-                count = arrayLength - (start - count + 1);
-                start = arrayLength - 1;
-            }
-        }
-
-        internal static int IndexOf(byte[]/*!*/ array, int arrayLength, char value, int start, int count) {
-            int end = start + NormalizeCount(arrayLength, start, count);
-            for (int i = start; i < end; i++) {
-                if (array[i] == value) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        internal static int IndexOf(char[]/*!*/ array, int arrayLength, byte value, int start, int count) {
-            int end = start + NormalizeCount(arrayLength, start, count);
-            for (int i = start; i < end; i++) {
-                if (array[i] == value) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        internal static int IndexOf(string/*!*/ str, byte value, int start, int count) {
-            int end = start + NormalizeCount(str.Length, start, count);
-            for (int i = start; i < end; i++) {
-                if (str[i] == value) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.IndexOf on ASCII strings.
-        /// </summary>
-        internal static int IndexOf(byte[]/*!*/ array, int arrayLength, string/*!*/ str, int start, int count) {
-            count = NormalizeCount(arrayLength, start, count);
-
-            int finish = start + count - str.Length;
-            for (int i = start; i <= finish; i++) {
-                bool match = true;
-                for (int j = 0; j < str.Length; j++) {
-                    if (str[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.IndexOf on ASCII strings.
-        /// </summary>
-        internal static int IndexOf(char[]/*!*/ array, int arrayLength, string/*!*/ str, int start, int count) {
-            count = NormalizeCount(arrayLength, start, count);
-
-            int finish = start + count - str.Length;
-            for (int i = start; i <= finish; i++) {
-                bool match = true;
-                for (int j = 0; j < str.Length; j++) {
-                    if (str[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.IndexOf on ASCII strings.
-        /// </summary>
-        internal static int IndexOf(byte[]/*!*/ array, int arrayLength, byte[]/*!*/ bytes, int start, int count) {
-            count = NormalizeCount(arrayLength, start, count);
-
-            int finish = start + count - bytes.Length;
-            for (int i = start; i <= finish; i++) {
-                bool match = true;
-                for (int j = 0; j < bytes.Length; j++) {
-                    if (bytes[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.IndexOf on ASCII strings.
-        /// </summary>
-        internal static int IndexOf(char[]/*!*/ array, int arrayLength, byte[]/*!*/ bytes, int start, int count) {
-            count = NormalizeCount(arrayLength, start, count);
-
-            int finish = start + count - bytes.Length;
-            for (int i = start; i <= finish; i++) {
-                bool match = true;
-                for (int j = 0; j < bytes.Length; j++) {
-                    if (bytes[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.IndexOf on ASCII strings.
-        /// </summary>
-        internal static int IndexOf(string/*!*/ str, byte[]/*!*/ bytes, int start, int count) {
-            count = NormalizeCount(str.Length, start, count);
-
-            int finish = start + count - bytes.Length;
-            for (int i = start; i <= finish; i++) {
-                bool match = true;
-                for (int j = 0; j < bytes.Length; j++) {
-                    if (bytes[j] != str[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        internal static int LastIndexOf(char[]/*!*/ array, int arrayLength, byte value, int start, int count) {
-            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
-            int end = start - count;
-            for (int i = start; i > end; i--) {
-                if (array[i] == value) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        internal static int LastIndexOf(string/*!*/ str, byte value, int start, int count) {
-            NormalizeLastIndexOfIndices(str.Length, ref start, ref count);
-            int end = start - count;
-            for (int i = start; i > end; i--) {
-                if (str[i] == value) {
-                    return i;
-                }
-            }
-
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
-        /// </summary>
-        internal static int LastIndexOf(byte[]/*!*/ array, int arrayLength, string/*!*/ value, int start, int count) {
-            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
-            int finish = start - count + 1;
-
-            if (value.Length == 0) {
-                return start;
-            }
-
-            for (int i = start - value.Length + 1; i >= finish; i--) {
-                bool match = true;
-                for (int j = 0; j < value.Length; j++) {
-                    if (value[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        internal static int LastIndexOf(char[]/*!*/ array, int arrayLength, string/*!*/ value, int start, int count) {
-            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
-            int finish = start - count + 1;
-
-            if (value.Length == 0) {
-                return start;
-            }
-
-            for (int i = start - value.Length + 1; i >= finish; i--) {
-                bool match = true;
-                for (int j = 0; j < value.Length; j++) {
-                    if (value[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
-        /// </summary>
-        internal static int LastIndexOf(byte[]/*!*/ array, int arrayLength, byte[]/*!*/ value, int start, int count) {
-            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
-            int finish = start - count + 1;
-
-            if (value.Length == 0) {
-                return start;
-            }
-
-            for (int i = start - value.Length + 1; i >= finish; i--) {
-                bool match = true;
-                for (int j = 0; j < value.Length; j++) {
-                    if (value[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
-        /// </summary>
-        internal static int LastIndexOf(char[]/*!*/ array, int arrayLength, byte[]/*!*/ value, int start, int count) {
-            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
-            int finish = start - count + 1;
-
-            if (value.Length == 0) {
-                return start;
-            }
-
-            for (int i = start - value.Length + 1; i >= finish; i--) {
-                bool match = true;
-                for (int j = 0; j < value.Length; j++) {
-                    if (value[j] != array[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        /// <summary>
-        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
-        /// </summary>
-        internal static int LastIndexOf(string/*!*/ str, byte[]/*!*/ value, int start, int count) {
-            NormalizeLastIndexOfIndices(str.Length, ref start, ref count);
-            int finish = start - count + 1;
-
-            if (value.Length == 0) {
-                return start;
-            }
-
-            for (int i = start - value.Length + 1; i >= finish; i--) {
-                bool match = true;
-                for (int j = 0; j < value.Length; j++) {
-                    if (value[j] != str[i + j]) {
-                        match = false;
-                        break;
-                    }
-                }
-
-                if (match) {
-                    return i;
-                }
-            }
-            return -1;
-        }
-
-        internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, byte[]/*!*/ other) {
-            return ValueCompareTo(array, itemCount, other, other.Length);
-        }
-
-        internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, byte[]/*!*/ other, int otherCount) {
-            int min = itemCount;
-            int defaultResult;
-            if (min < otherCount) {
-                defaultResult = -1;
-            } else if (min > otherCount) {
-                min = otherCount;
-                defaultResult = +1;
-            } else {
-                defaultResult = 0;
-            }
-
-            for (int i = 0; i < min; i++) {
-                if (array[i] != other[i]) {
-                    return (int)array[i] - other[i];
-                }
-            }
-
-            return defaultResult;
-        }
-
-        internal static int ValueCompareTo(this char[]/*!*/ array, int itemCount, char[]/*!*/ other, int otherCount) {
-            int min = itemCount;
-            int defaultResult;
-            if (min < otherCount) {
-                defaultResult = -1;
-            } else if (min > otherCount) {
-                min = otherCount;
-                defaultResult = +1;
-            } else {
-                defaultResult = 0;
-            }
-
-            for (int i = 0; i < min; i++) {
-                if (array[i] != other[i]) {
-                    return (int)array[i] - other[i];
-                }
-            }
-
-            return defaultResult;
-        }
-
-        internal static int ValueCompareTo(this char[]/*!*/ array, int itemCount, string/*!*/ other) {
-            int min = itemCount, defaultResult;
-            if (min < other.Length) {
-                defaultResult = -1;
-            } else if (min > other.Length) {
-                min = other.Length;
-                defaultResult = +1;
-            } else {
-                defaultResult = 0;
-            }
-
-            for (int i = 0; i < min; i++) {
-                if (array[i] != other[i]) {
-                    return (int)array[i] - other[i];
-                }
-            }
-
-            return defaultResult;
-        }
-
-        internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, string/*!*/ other) {
-            int min = itemCount;
-            int defaultResult;
-            if (min < other.Length) {
-                defaultResult = -1;
-            } else if (min > other.Length) {
-                min = other.Length;
-                defaultResult = +1;
-            } else {
-                defaultResult = 0;
-            }
-
-            for (int i = 0; i < min; i++) {
-                if (array[i] != other[i]) {
-                    return (int)array[i] - other[i];
-                }
-            }
-
-            return defaultResult;
-        }
-
-        internal static int ValueCompareTo(this string/*!*/ str, string/*!*/ other) {
-            int min = str.Length, defaultResult;
-            if (min < other.Length) {
-                defaultResult = -1;
-            } else if (min > other.Length) {
-                min = other.Length;
-                defaultResult = +1;
-            } else {
-                defaultResult = 0;
-            }
-
-            for (int i = 0; i < min; i++) {
-                if (str[i] != other[i]) {
-                    return (int)str[i] - other[i];
-                }
-            }
-
-            return defaultResult;
-        }
-
-        internal static bool SubstringEquals(string/*!*/ name, int start, int count, string/*!*/ other) {
-            if (count != other.Length) {
-                return false;
-            }
-
-            for (int i = 0; i < count; i++) {
-                if (name[start + i] != other[i]) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        internal static bool ValueEquals<T>(T[] array, int arrayCount, T[] other, int otherCount) {
-            Debug.Assert(arrayCount <= array.Length);
-            Debug.Assert(otherCount <= other.Length);
-
-            if (arrayCount != otherCount) {
-                return false;
-            }
-
-            for (int i = 0; i < arrayCount; i++) {
-                if (!Object.Equals(array[i], other[i])) {
-                    return false;
-                }
-            }
-
-            return true;
-        }
-
-        public static TOutput[]/*!*/ ConvertAll<TInput, TOutput>(this TInput[]/*!*/ array, Func<TInput, TOutput>/*!*/ converter) {
-            var result = new TOutput[array.Length];
-            for (int i = 0; i < array.Length; i++) {
-                result[i] = converter(array[i]);
-            }
-            return result;
-        }
-
-        internal static void AddRange(IList/*!*/ list, IList/*!*/ range) {
-            Assert.NotNull(list, range);
-
-            List<object> objList;
-            IEnumerable<object> enumerableRange;
-            RubyArray array;
-            if ((array = list as RubyArray) != null) {
-                array.AddRange(range);
-            } else if ((objList = list as List<object>) != null && (enumerableRange = range as IEnumerable<object>) != null) {
-                objList.AddRange(enumerableRange);
-            } else {
-                foreach (var item in range) {
-                    list.Add(item);
-                }
-            }
-        }
-
-        [Conditional("DEBUG")]
-        public static void Log(string/*!*/ message, string/*!*/ category) {
+#endif
+
+using System;
+using System.Globalization;
+using System.Diagnostics;
+using System.Text;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using System.Dynamic;
+using Microsoft.Scripting.Utils;
+using IronRuby.Builtins;
+using Microsoft.Scripting;
+using System.Text.RegularExpressions;
+
+namespace IronRuby.Runtime {
+    public static class Utils {
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+        public static readonly byte[] EmptyBytes = new byte[0];
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+        public static readonly char[] EmptyChars = new char[0];
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+        public static readonly MemberInfo[] EmptyMemberInfos = new MemberInfo[0];
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2105:ArrayFieldsShouldNotBeReadOnly")]
+        public static readonly Delegate[] EmptyDelegates = new Delegate[0];
+
+        public static int IndexOf(this string[]/*!*/ array, string/*!*/ value, StringComparer/*!*/ comparer) {
+            ContractUtils.RequiresNotNull(array, "array");
+            ContractUtils.RequiresNotNull(value, "value");
+            ContractUtils.RequiresNotNull(comparer, "comparer");
+
+            for (int i = 0; i < array.Length; i++) {
+                if (comparer.Equals(array[i], value)) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        public static bool IsAscii(this string/*!*/ str) {
+            for (int i = 0; i < str.Length; i++) {
+                if (str[i] > 0x7f) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsAscii(this byte[]/*!*/ bytes, int count) {
+            for (int i = 0; i < count; i++) {
+                if (bytes[i] > 0x7f) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsAscii(this char[]/*!*/ str, int count) {
+            for (int i = 0; i < count; i++) {
+                if (str[i] > 0x7f) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsAscii(this char[]/*!*/ str, int start, int count) {
+            for (int i = 0; i < count; i++) {
+                if (str[start + i] > 0x7f) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        internal static bool IsBinary(this string/*!*/ str) {
+            for (int i = 0; i < str.Length; i++) {
+                if (str[i] > 0xff) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        internal static int GetCharacterCount(this string/*!*/ str) {
+            int surrogateCount = 0;
+            bool wasHighSurrogate = false;
+            for (int i = 0; i < str.Length; i++) {
+                char c = str[i];
+                if (c >= '\uD800') {
+                    if (c <= '\uDBFF') {
+                        wasHighSurrogate = true;
+                    } else if (wasHighSurrogate && c <= '\uDFFF') {
+                        surrogateCount++;
+                        wasHighSurrogate = false;
+                    }
+                }
+            }
+            return str.Length - surrogateCount;
+        }
+
+        /// <summary>
+        /// Calculates the number of Unicode characters in given array.
+        /// Assumes that the content of the array beyond count chars doesn't contain significant data and can be overwritten.
+        /// </summary>
+        internal static int GetCharacterCount(this char[]/*!*/ str, int count) {
+            int surrogateCount = 0;
+            bool wasHighSurrogate = false;
+            if (count < str.Length) {
+                str[count] = '\uffff';
+            }
+
+            for (int i = 0; i < str.Length; i++) {
+                char c = str[i];
+                if (c >= '\uD800') {
+                    if (i >= count) {
+                        break;
+                    } else if (c <= '\uDBFF') {
+                        wasHighSurrogate = true;
+                    } else if (wasHighSurrogate && c <= '\uDFFF') {
+                        surrogateCount++;
+                        wasHighSurrogate = false;
+                    }
+                }
+            }
+            return str.Length - surrogateCount;
+        }
+
+        public static string/*!*/ ToAsciiString(this string/*!*/ str) {
+            return MutableString.AppendUnicodeRepresentation(new StringBuilder(), str, MutableString.Escape.NonAscii, -1, -1).ToString();
+        }
+
+        public static int LastCharacter(this string/*!*/ str) {
+            return str.Length == 0 ? -1 : str[str.Length - 1];
+        }
+
+        internal static IEnumerable<byte>/*!*/ EnumerateAsBytes(char[]/*!*/ data, int count) {
+            for (int i = 0; i < count; i++) {
+                yield return (byte)data[i];
+            }
+        }
+
+        internal static IEnumerable<byte>/*!*/ EnumerateAsBytes(string/*!*/ data) {
+            for (int i = 0; i < data.Length; i++) {
+                yield return (byte)data[i];
+            }
+        }
+
+        internal static IEnumerable<T>/*!*/ Enumerate<T>(T[]/*!*/ data, int count) {
+            for (int i = 0; i < count; i++) {
+                yield return data[i];
+            }
+        }
+
+        internal const int MinListSize = 4;
+        internal const int MinBufferSize = 16;
+
+        internal static int GetExpandedSize<T>(T[]/*!*/ array, int minLength) {
+            return Math.Max(minLength, Math.Max(1 + (array.Length << 1), typeof(T) == typeof(object) ? MinListSize : MinBufferSize));
+        }
+
+        internal static void Resize<T>(ref T[]/*!*/ array, int minLength) {
+            if (array.Length < minLength) {
+                Array.Resize(ref array, GetExpandedSize(array, minLength));
+            }
+        }
+
+        internal static void TrimExcess<T>(ref T[] data, int count) {
+            if (IsSparse(count, data.Length)) {
+                Array.Resize(ref data, count);
+            }
+        }
+
+        internal static bool IsSparse(int portionSize, int totalSize) {
+            Debug.Assert(portionSize <= totalSize);
+            return (long)portionSize * 10 < (long)totalSize * 9;
+        }
+
+        internal static void ResizeForInsertion<T>(ref T[]/*!*/ array, int itemCount, int index, int count) {
+            int minLength = itemCount + count;
+            T[] a;
+            if (array.Length < minLength) {
+                a = new T[GetExpandedSize(array, minLength)];
+                Array.Copy(array, 0, a, 0, index);
+            } else {
+                a = array;
+            }
+
+            Array.Copy(array, index, a, index + count, itemCount - index);
+            array = a;
+        }
+
+        internal static void Fill<T>(T[]/*!*/ array, int index, T item, int repeatCount) {
+            // TODO: can be optimized for big repeatCount:
+            for (int i = index; i < index + repeatCount; i++) {
+                array[i] = item;
+            }
+        }
+
+        private static void Fill(byte[]/*!*/ src, int srcStart, byte[]/*!*/ dst, int dstStart, int count, int repeatCount) {
+            // TODO: can be optimized for big repeatCount or big count:
+            if (count == 1) {
+                Fill(dst, dstStart, src[srcStart], repeatCount);
+            } else {
+                for (int i = 0; i < repeatCount; i++) {
+                    for (int j = 0; j < count; j++) {
+                        dst[dstStart++] = src[srcStart + j];
+                    }
+                }
+            }
+        }
+
+        private static int GetByteCount(string/*!*/ str, int start, int count, Encoding/*!*/ encoding, out char[]/*!*/ chars) {
+            // TODO: we can special case this for some encodings and calculate the byte count w/o copying the content: 
+            chars = new char[count];
+            str.CopyTo(start, chars, 0, count);
+            return encoding.GetByteCount(chars, 0, chars.Length);
+        }
+
+        internal static T[]/*!*/ Concatenate<T>(T[]/*!*/ array1, T[]/*!*/ array2) {
+            return Concatenate(array1, array1.Length, array2, array2.Length);
+        }
+
+        internal static T[]/*!*/ Concatenate<T>(params T[][] arrays) {
+            int length = 0;
+            foreach (var array in arrays) {
+                length += array.Length;
+            }
+
+            T[] result = new T[length];
+            length = 0;
+            foreach (var array in arrays) {
+                Array.Copy(array, 0, result, length, array.Length);
+                length += array.Length;
+            }
+            return result;
+        }
+
+        internal static T[]/*!*/ Concatenate<T>(T[]/*!*/ array1, int itemCount1, T[]/*!*/ array2, int itemCount2) {
+            T[] result = new T[itemCount1 + itemCount2];
+            Array.Copy(array1, 0, result, 0, itemCount1);
+            Array.Copy(array2, 0, result, itemCount1, itemCount2);
+            return result;
+        }
+
+        internal static int Append<T>(ref T[]/*!*/ array, int itemCount, T item, int repeatCount) {
+            Resize(ref array, itemCount + repeatCount);
+            Fill(array, itemCount, item, repeatCount);
+            return itemCount + repeatCount;
+        }
+
+        internal static int Append(ref char[]/*!*/ array, int itemCount, string/*!*/ other, int start, int count) {
+            int newCount = itemCount + count;
+            Resize(ref array, newCount);
+            other.CopyTo(start, array, itemCount, count);
+            return newCount;
+        }
+
+        internal static int Append<T>(ref T[]/*!*/ array, int itemCount, T[]/*!*/ other, int start, int count) {
+            int newCount = itemCount + count;
+            Resize(ref array, newCount);
+            Array.Copy(other, start, array, itemCount, count);
+            return newCount;
+        }
+
+        internal static int Append(ref byte[]/*!*/ array, int itemCount, string/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
+            char[] appendChars;
+            int newCount = itemCount + GetByteCount(other, start, count, encoding, out appendChars);
+            Resize(ref array, newCount);
+            encoding.GetBytes(appendChars, 0, appendChars.Length, array, itemCount);
+            return newCount;
+        }
+
+        internal static int Append(ref byte[]/*!*/ array, int itemCount, char[]/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
+            int newCount = itemCount + encoding.GetByteCount(other, start, count);
+            Resize(ref array, newCount);
+            encoding.GetBytes(other, start, count, array, itemCount);
+            return newCount;
+        }
+
+        internal static int Append(ref byte[]/*!*/ array, int itemCount, char other, int repeatCount, Encoding/*!*/ encoding) {
+            if (repeatCount == 0) {
+                return itemCount;
+            }
+
+            char[] chars = new char[] { other };
+            int charSize = encoding.GetByteCount(chars, 0, 1);
+            int newCount = itemCount + charSize * repeatCount;
+            Resize(ref array, newCount);
+
+            encoding.GetBytes(chars, 0, 1, array, itemCount);
+            Fill(array, itemCount, array, itemCount + charSize, charSize, repeatCount - 1);
+
+            return newCount;
+        }
+
+        internal static int InsertAt<T>(ref T[]/*!*/ array, int itemCount, int index, T other, int repeatCount) {
+            ResizeForInsertion(ref array, itemCount, index, repeatCount);
+            Fill(array, index, other, repeatCount);
+            return itemCount + repeatCount;
+        }
+
+        internal static int InsertAt(ref char[]/*!*/ array, int itemCount, int index, string/*!*/ other, int start, int count) {
+            ResizeForInsertion(ref array, itemCount, index, count);
+            other.CopyTo(start, array, index, count);
+            return itemCount + count;
+        }
+
+        internal static int InsertAt<T>(ref T[]/*!*/ array, int itemCount, int index, T[]/*!*/ other, int start, int count) {
+            ResizeForInsertion(ref array, itemCount, index, count);
+            Array.Copy(other, start, array, index, count);
+            return itemCount + count;
+        }
+
+        internal static int InsertAt(ref byte[]/*!*/ array, int itemCount, int index, string/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
+            char[] insertChars;
+            int insertedCount = GetByteCount(other, start, count, encoding, out insertChars);
+            ResizeForInsertion(ref array, itemCount, index, insertedCount);
+            encoding.GetBytes(insertChars, 0, insertChars.Length, array, itemCount);
+            return itemCount + insertedCount;
+        }
+
+        internal static int InsertAt(ref byte[]/*!*/ array, int itemCount, int index, char[]/*!*/ other, int start, int count, Encoding/*!*/ encoding) {
+            int insertedCount = encoding.GetByteCount(other, start, count);
+            ResizeForInsertion(ref array, itemCount, index, insertedCount);
+            encoding.GetBytes(other, start, count, array, itemCount);
+            return itemCount + insertedCount;
+        }
+
+        internal static int InsertAt(ref byte[]/*!*/ array, int itemCount, int index, char other, int repeatCount, Encoding/*!*/ encoding) {
+            if (repeatCount == 0) {
+                return itemCount;
+            }
+
+            char[] chars = new char[] { other };
+            int charSize = encoding.GetByteCount(chars, 0, 1);
+            int insertedCount = charSize * repeatCount;
+
+            ResizeForInsertion(ref array, itemCount, index, insertedCount);
+
+            // first character:
+            encoding.GetBytes(chars, 0, 1, array, itemCount);
+            Fill(array, itemCount, array, itemCount + charSize, charSize, repeatCount - 1);
+            return itemCount + insertedCount;
+        }
+
+        internal static int Remove<T>(ref T[]/*!*/ array, int itemCount, int start, int count) {
+            T[] a;
+            int remaining = itemCount - count;
+            if (remaining > MinBufferSize && remaining < itemCount / 2) {
+                a = new T[remaining];
+                Array.Copy(array, 0, a, 0, start);
+            } else {
+                a = array;
+            }
+
+            Array.Copy(array, start + count, a, start, remaining - start);
+            array = a;
+            return remaining;
+        }
+
+        internal static T[]/*!*/ GetSlice<T>(this T[]/*!*/ array, int start, int count) {
+            var copy = new T[count];
+            Array.Copy(array, start, copy, 0, count);
+            return copy;
+        }
+
+        internal static T[]/*!*/ GetSlice<T>(this T[]/*!*/ array, int arrayLength, int start, int count) {
+            count = NormalizeCount(arrayLength, start, count);
+            var copy = new T[count];
+            if (count > 0) {
+                Array.Copy(array, start, copy, 0, count);
+            }
+            return copy;
+        }
+
+        internal static string/*!*/ GetSlice(this string/*!*/ str, int start, int count) {
+            count = NormalizeCount(str.Length, start, count);
+            return count > 0 ? str.Substring(start, count) : String.Empty;
+        }
+
+        internal static string/*!*/ GetStringSlice(this char[]/*!*/ chars, int arrayLength, int start, int count) {
+            count = NormalizeCount(arrayLength, start, count);
+            return count > 0 ? new String(chars, start, count) : String.Empty;
+        }
+
+        internal static int NormalizeCount(int arrayLength, int start, int count) {
+            if (count > arrayLength - start) {
+                return start >= arrayLength ? 0 : arrayLength - start;
+            } else {
+                return count;
+            }
+        }
+
+        internal static void NormalizeLastIndexOfIndices(int arrayLength, ref int start, ref int count) {
+            if (start >= arrayLength) {
+                count = arrayLength - (start - count + 1);
+                start = arrayLength - 1;
+            }
+        }
+
+        internal static int IndexOf(byte[]/*!*/ array, int arrayLength, char value, int start, int count) {
+            int end = start + NormalizeCount(arrayLength, start, count);
+            for (int i = start; i < end; i++) {
+                if (array[i] == value) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        internal static int IndexOf(char[]/*!*/ array, int arrayLength, byte value, int start, int count) {
+            int end = start + NormalizeCount(arrayLength, start, count);
+            for (int i = start; i < end; i++) {
+                if (array[i] == value) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        internal static int IndexOf(string/*!*/ str, byte value, int start, int count) {
+            int end = start + NormalizeCount(str.Length, start, count);
+            for (int i = start; i < end; i++) {
+                if (str[i] == value) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.IndexOf on ASCII strings.
+        /// </summary>
+        internal static int IndexOf(byte[]/*!*/ array, int arrayLength, string/*!*/ str, int start, int count) {
+            count = NormalizeCount(arrayLength, start, count);
+
+            int finish = start + count - str.Length;
+            for (int i = start; i <= finish; i++) {
+                bool match = true;
+                for (int j = 0; j < str.Length; j++) {
+                    if (str[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.IndexOf on ASCII strings.
+        /// </summary>
+        internal static int IndexOf(char[]/*!*/ array, int arrayLength, string/*!*/ str, int start, int count) {
+            count = NormalizeCount(arrayLength, start, count);
+
+            int finish = start + count - str.Length;
+            for (int i = start; i <= finish; i++) {
+                bool match = true;
+                for (int j = 0; j < str.Length; j++) {
+                    if (str[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.IndexOf on ASCII strings.
+        /// </summary>
+        internal static int IndexOf(byte[]/*!*/ array, int arrayLength, byte[]/*!*/ bytes, int start, int count) {
+            count = NormalizeCount(arrayLength, start, count);
+
+            int finish = start + count - bytes.Length;
+            for (int i = start; i <= finish; i++) {
+                bool match = true;
+                for (int j = 0; j < bytes.Length; j++) {
+                    if (bytes[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.IndexOf on ASCII strings.
+        /// </summary>
+        internal static int IndexOf(char[]/*!*/ array, int arrayLength, byte[]/*!*/ bytes, int start, int count) {
+            count = NormalizeCount(arrayLength, start, count);
+
+            int finish = start + count - bytes.Length;
+            for (int i = start; i <= finish; i++) {
+                bool match = true;
+                for (int j = 0; j < bytes.Length; j++) {
+                    if (bytes[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.IndexOf on ASCII strings.
+        /// </summary>
+        internal static int IndexOf(string/*!*/ str, byte[]/*!*/ bytes, int start, int count) {
+            count = NormalizeCount(str.Length, start, count);
+
+            int finish = start + count - bytes.Length;
+            for (int i = start; i <= finish; i++) {
+                bool match = true;
+                for (int j = 0; j < bytes.Length; j++) {
+                    if (bytes[j] != str[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        internal static int LastIndexOf(char[]/*!*/ array, int arrayLength, byte value, int start, int count) {
+            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
+            int end = start - count;
+            for (int i = start; i > end; i--) {
+                if (array[i] == value) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        internal static int LastIndexOf(string/*!*/ str, byte value, int start, int count) {
+            NormalizeLastIndexOfIndices(str.Length, ref start, ref count);
+            int end = start - count;
+            for (int i = start; i > end; i--) {
+                if (str[i] == value) {
+                    return i;
+                }
+            }
+
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
+        /// </summary>
+        internal static int LastIndexOf(byte[]/*!*/ array, int arrayLength, string/*!*/ value, int start, int count) {
+            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
+            int finish = start - count + 1;
+
+            if (value.Length == 0) {
+                return start;
+            }
+
+            for (int i = start - value.Length + 1; i >= finish; i--) {
+                bool match = true;
+                for (int j = 0; j < value.Length; j++) {
+                    if (value[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        internal static int LastIndexOf(char[]/*!*/ array, int arrayLength, string/*!*/ value, int start, int count) {
+            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
+            int finish = start - count + 1;
+
+            if (value.Length == 0) {
+                return start;
+            }
+
+            for (int i = start - value.Length + 1; i >= finish; i--) {
+                bool match = true;
+                for (int j = 0; j < value.Length; j++) {
+                    if (value[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
+        /// </summary>
+        internal static int LastIndexOf(byte[]/*!*/ array, int arrayLength, byte[]/*!*/ value, int start, int count) {
+            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
+            int finish = start - count + 1;
+
+            if (value.Length == 0) {
+                return start;
+            }
+
+            for (int i = start - value.Length + 1; i >= finish; i--) {
+                bool match = true;
+                for (int j = 0; j < value.Length; j++) {
+                    if (value[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
+        /// </summary>
+        internal static int LastIndexOf(char[]/*!*/ array, int arrayLength, byte[]/*!*/ value, int start, int count) {
+            NormalizeLastIndexOfIndices(arrayLength, ref start, ref count);
+            int finish = start - count + 1;
+
+            if (value.Length == 0) {
+                return start;
+            }
+
+            for (int i = start - value.Length + 1; i >= finish; i--) {
+                bool match = true;
+                for (int j = 0; j < value.Length; j++) {
+                    if (value[j] != array[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// Implements the same behavior as String.LastIndexOf on ASCII strings.
+        /// </summary>
+        internal static int LastIndexOf(string/*!*/ str, byte[]/*!*/ value, int start, int count) {
+            NormalizeLastIndexOfIndices(str.Length, ref start, ref count);
+            int finish = start - count + 1;
+
+            if (value.Length == 0) {
+                return start;
+            }
+
+            for (int i = start - value.Length + 1; i >= finish; i--) {
+                bool match = true;
+                for (int j = 0; j < value.Length; j++) {
+                    if (value[j] != str[i + j]) {
+                        match = false;
+                        break;
+                    }
+                }
+
+                if (match) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, byte[]/*!*/ other) {
+            return ValueCompareTo(array, itemCount, other, other.Length);
+        }
+
+        internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, byte[]/*!*/ other, int otherCount) {
+            int min = itemCount;
+            int defaultResult;
+            if (min < otherCount) {
+                defaultResult = -1;
+            } else if (min > otherCount) {
+                min = otherCount;
+                defaultResult = +1;
+            } else {
+                defaultResult = 0;
+            }
+
+            for (int i = 0; i < min; i++) {
+                if (array[i] != other[i]) {
+                    return (int)array[i] - other[i];
+                }
+            }
+
+            return defaultResult;
+        }
+
+        internal static int ValueCompareTo(this char[]/*!*/ array, int itemCount, char[]/*!*/ other, int otherCount) {
+            int min = itemCount;
+            int defaultResult;
+            if (min < otherCount) {
+                defaultResult = -1;
+            } else if (min > otherCount) {
+                min = otherCount;
+                defaultResult = +1;
+            } else {
+                defaultResult = 0;
+            }
+
+            for (int i = 0; i < min; i++) {
+                if (array[i] != other[i]) {
+                    return (int)array[i] - other[i];
+                }
+            }
+
+            return defaultResult;
+        }
+
+        internal static int ValueCompareTo(this char[]/*!*/ array, int itemCount, string/*!*/ other) {
+            int min = itemCount, defaultResult;
+            if (min < other.Length) {
+                defaultResult = -1;
+            } else if (min > other.Length) {
+                min = other.Length;
+                defaultResult = +1;
+            } else {
+                defaultResult = 0;
+            }
+
+            for (int i = 0; i < min; i++) {
+                if (array[i] != other[i]) {
+                    return (int)array[i] - other[i];
+                }
+            }
+
+            return defaultResult;
+        }
+
+        internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, string/*!*/ other) {
+            int min = itemCount;
+            int defaultResult;
+            if (min < other.Length) {
+                defaultResult = -1;
+            } else if (min > other.Length) {
+                min = other.Length;
+                defaultResult = +1;
+            } else {
+                defaultResult = 0;
+            }
+
+            for (int i = 0; i < min; i++) {
+                if (array[i] != other[i]) {
+                    return (int)array[i] - other[i];
+                }
+            }
+
+            return defaultResult;
+        }
+
+        internal static int ValueCompareTo(this string/*!*/ str, string/*!*/ other) {
+            int min = str.Length, defaultResult;
+            if (min < other.Length) {
+                defaultResult = -1;
+            } else if (min > other.Length) {
+                min = other.Length;
+                defaultResult = +1;
+            } else {
+                defaultResult = 0;
+            }
+
+            for (int i = 0; i < min; i++) {
+                if (str[i] != other[i]) {
+                    return (int)str[i] - other[i];
+                }
+            }
+
+            return defaultResult;
+        }
+
+        internal static bool SubstringEquals(string/*!*/ name, int start, int count, string/*!*/ other) {
+            if (count != other.Length) {
+                return false;
+            }
+
+            for (int i = 0; i < count; i++) {
+                if (name[start + i] != other[i]) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        internal static bool ValueEquals<T>(T[] array, int arrayCount, T[] other, int otherCount) {
+            Debug.Assert(arrayCount <= array.Length);
+            Debug.Assert(otherCount <= other.Length);
+
+            if (arrayCount != otherCount) {
+                return false;
+            }
+
+            for (int i = 0; i < arrayCount; i++) {
+                if (!Object.Equals(array[i], other[i])) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        public static TOutput[]/*!*/ ConvertAll<TInput, TOutput>(this TInput[]/*!*/ array, Func<TInput, TOutput>/*!*/ converter) {
+            var result = new TOutput[array.Length];
+            for (int i = 0; i < array.Length; i++) {
+                result[i] = converter(array[i]);
+            }
+            return result;
+        }
+
+        internal static void AddRange(IList/*!*/ list, IList/*!*/ range) {
+            Assert.NotNull(list, range);
+
+            List<object> objList;
+            IEnumerable<object> enumerableRange;
+            RubyArray array;
+            if ((array = list as RubyArray) != null) {
+                array.AddRange(range);
+            } else if ((objList = list as List<object>) != null && (enumerableRange = range as IEnumerable<object>) != null) {
+                objList.AddRange(enumerableRange);
+            } else {
+                foreach (var item in range) {
+                    list.Add(item);
+                }
+            }
+        }
+
+        [Conditional("DEBUG")]
+        public static void Log(string/*!*/ message, string/*!*/ category) {
+            if (Environment.GetEnvironmentVariable("IR_DEBUG_LOG") != null) {
 #if WIN8 || ANDROID || WP75
-            Debug.WriteLine(category + ": " + message);
-#elif !SILVERLIGHT
-            Debug.WriteLine((object)message, category);
-#endif
-        }
-
-        public static long DateTimeTicksFromStopwatch(long elapsedStopwatchTicks) {
-#if !SILVERLIGHT && !WP75
-            if (Stopwatch.IsHighResolution) {
-                return (long)(((double)elapsedStopwatchTicks) * 10000000.0 / (double)Stopwatch.Frequency);
-            }
-#endif
-            return elapsedStopwatchTicks;
-        }
-
-        public static char ToLowerHexDigit(this int digit) {
-            return (char)((digit < 10) ? '0' + digit : 'a' + digit - 10);
-        }
-
-        public static char ToUpperHexDigit(this int digit) {
-            return (char)((digit < 10) ? '0' + digit : 'A' + digit - 10);
-        }
-
-        public static char ToUpperInvariant(this char c) {
-            return Char.ToUpperInvariant(c);
-        }
-
-        public static char ToLowerInvariant(this char c) {
-            return Char.ToLowerInvariant(c);
-        }
-
+                Debug.WriteLine(category + ": " + message);
+#elif !SILVERLIGHT
+                Debug.WriteLine((object)message, category);
+#endif
+            }
+        }
+
+        public static long DateTimeTicksFromStopwatch(long elapsedStopwatchTicks) {
+#if !SILVERLIGHT && !WP75
+            if (Stopwatch.IsHighResolution) {
+                return (long)(((double)elapsedStopwatchTicks) * 10000000.0 / (double)Stopwatch.Frequency);
+            }
+#endif
+            return elapsedStopwatchTicks;
+        }
+
+        public static char ToLowerHexDigit(this int digit) {
+            return (char)((digit < 10) ? '0' + digit : 'a' + digit - 10);
+        }
+
+        public static char ToUpperHexDigit(this int digit) {
+            return (char)((digit < 10) ? '0' + digit : 'A' + digit - 10);
+        }
+
+        public static char ToUpperInvariant(this char c) {
+            return Char.ToUpperInvariant(c);
+        }
+
+        public static char ToLowerInvariant(this char c) {
+            return Char.ToLowerInvariant(c);
+        }
+
 #if SILVERLIGHT
         public static string/*!*/ ToUpperInvariant(this string/*!*/ str) {
             return str.ToUpper(CultureInfo.InvariantCulture);
@@ -929,134 +932,134 @@ public static class Utils {
         public static string/*!*/ ToLowerInvariant(this string/*!*/ str) {
             return str.ToLower(CultureInfo.InvariantCulture);
         }
-#endif
-        internal static IEnumerable<Expression/*!*/>/*!*/ ToExpressions(this IEnumerable<DynamicMetaObject>/*!*/ metaObjects) {
-            foreach (var metaObject in metaObjects) {
-                yield return metaObject != null ? metaObject.Expression : null;
-            }
-        }
-
-        internal static Action<RubyModule> CloneInvocationChain(Action<RubyModule> chain) {
-            if (chain == null) {
-                return null;
-            }
-
-            Action<RubyModule> result = _ => { };
-            foreach (var d in chain.GetInvocationList()) {
-                result += (Action<RubyModule>)d;
-            }
-
-            return result;
-        }
-
-        internal static void CopyTupleFields(MutableTuple/*!*/ src, MutableTuple/*!*/ dst) {
-            Debug.Assert(src.Capacity == dst.Capacity);
-            for (int i = 0; i < src.Capacity; i++) {
-                dst.SetValue(i, src.GetValue(i));
-            }
-        }
-
-#if FEATURE_ENCODING
-        private sealed class CheckDecoderFallback : DecoderFallback {
-            public bool HasInvalidCharacters { get; private set; }
-
-            public CheckDecoderFallback() {
-            }
-
-            public override int MaxCharCount {
-                get { return 1; }
-            }
-
-            public override DecoderFallbackBuffer CreateFallbackBuffer() {
-                return new Buffer(this);
-            }
-
-            internal sealed class Buffer : DecoderFallbackBuffer {
-                private readonly CheckDecoderFallback _fallback;
-
-                public Buffer(CheckDecoderFallback/*!*/ fallback) {
-                    _fallback = fallback;
-                }
-
-                public override bool Fallback(byte[]/*!*/ bytesUnknown, int index) {
-                    _fallback.HasInvalidCharacters = true;
-                    return true;
-                }
-
-                public override char GetNextChar() {
-                    return '\0';
-                }
-
-                public override bool MovePrevious() {
-                    return false;
-                }
-
-                public override int Remaining {
-                    get { return 0; }
-                }
-            }
-        }
-
-        private sealed class CheckEncoderFallback : EncoderFallback {
-            public bool HasInvalidCharacters { get; private set; }
-
-            public CheckEncoderFallback() {
-            }
-
-            public override int MaxCharCount {
-                get { return 1; }
-            }
-
-            public override EncoderFallbackBuffer CreateFallbackBuffer() {
-                return new Buffer(this);
-            }
-
-            internal sealed class Buffer : EncoderFallbackBuffer {
-                private readonly CheckEncoderFallback _fallback;
-
-                public Buffer(CheckEncoderFallback/*!*/ fallback) {
-                    _fallback = fallback;
-                }
-
-                public override bool Fallback(char charUnknown, int index) {
-                    _fallback.HasInvalidCharacters = true;
-                    return true;
-                }
-
-                public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index) {
-                    _fallback.HasInvalidCharacters = true;
-                    return true;
-                }
-
-                public override char GetNextChar() {
-                    return '\0';
-                }
-
-                public override bool MovePrevious() {
-                    return false;
-                }
-
-                public override int Remaining {
-                    get { return 0; }
-                }
-            }
-        }
-
-        internal static bool ContainsInvalidCharacters(byte[]/*!*/ bytes, int start, int count, Encoding/*!*/ encoding) {
-            var decoder = encoding.GetDecoder();
-            var fallback = new CheckDecoderFallback();
-            decoder.Fallback = fallback;
-            decoder.GetCharCount(bytes, start, count, true);
-            return fallback.HasInvalidCharacters;
-        }
-
-        internal static bool ContainsInvalidCharacters(char[]/*!*/ chars, int start, int count, Encoding/*!*/ encoding) {
-            var encoder = encoding.GetEncoder();
-            var fallback = new CheckEncoderFallback();
-            encoder.Fallback = fallback;
-            encoder.GetByteCount(chars, start, count, true);
-            return fallback.HasInvalidCharacters;
-        }
+#endif
+        internal static IEnumerable<Expression/*!*/>/*!*/ ToExpressions(this IEnumerable<DynamicMetaObject>/*!*/ metaObjects) {
+            foreach (var metaObject in metaObjects) {
+                yield return metaObject != null ? metaObject.Expression : null;
+            }
+        }
+
+        internal static Action<RubyModule> CloneInvocationChain(Action<RubyModule> chain) {
+            if (chain == null) {
+                return null;
+            }
+
+            Action<RubyModule> result = _ => { };
+            foreach (var d in chain.GetInvocationList()) {
+                result += (Action<RubyModule>)d;
+            }
+
+            return result;
+        }
+
+        internal static void CopyTupleFields(MutableTuple/*!*/ src, MutableTuple/*!*/ dst) {
+            Debug.Assert(src.Capacity == dst.Capacity);
+            for (int i = 0; i < src.Capacity; i++) {
+                dst.SetValue(i, src.GetValue(i));
+            }
+        }
+
+#if FEATURE_ENCODING
+        private sealed class CheckDecoderFallback : DecoderFallback {
+            public bool HasInvalidCharacters { get; private set; }
+
+            public CheckDecoderFallback() {
+            }
+
+            public override int MaxCharCount {
+                get { return 1; }
+            }
+
+            public override DecoderFallbackBuffer CreateFallbackBuffer() {
+                return new Buffer(this);
+            }
+
+            internal sealed class Buffer : DecoderFallbackBuffer {
+                private readonly CheckDecoderFallback _fallback;
+
+                public Buffer(CheckDecoderFallback/*!*/ fallback) {
+                    _fallback = fallback;
+                }
+
+                public override bool Fallback(byte[]/*!*/ bytesUnknown, int index) {
+                    _fallback.HasInvalidCharacters = true;
+                    return true;
+                }
+
+                public override char GetNextChar() {
+                    return '\0';
+                }
+
+                public override bool MovePrevious() {
+                    return false;
+                }
+
+                public override int Remaining {
+                    get { return 0; }
+                }
+            }
+        }
+
+        private sealed class CheckEncoderFallback : EncoderFallback {
+            public bool HasInvalidCharacters { get; private set; }
+
+            public CheckEncoderFallback() {
+            }
+
+            public override int MaxCharCount {
+                get { return 1; }
+            }
+
+            public override EncoderFallbackBuffer CreateFallbackBuffer() {
+                return new Buffer(this);
+            }
+
+            internal sealed class Buffer : EncoderFallbackBuffer {
+                private readonly CheckEncoderFallback _fallback;
+
+                public Buffer(CheckEncoderFallback/*!*/ fallback) {
+                    _fallback = fallback;
+                }
+
+                public override bool Fallback(char charUnknown, int index) {
+                    _fallback.HasInvalidCharacters = true;
+                    return true;
+                }
+
+                public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index) {
+                    _fallback.HasInvalidCharacters = true;
+                    return true;
+                }
+
+                public override char GetNextChar() {
+                    return '\0';
+                }
+
+                public override bool MovePrevious() {
+                    return false;
+                }
+
+                public override int Remaining {
+                    get { return 0; }
+                }
+            }
+        }
+
+        internal static bool ContainsInvalidCharacters(byte[]/*!*/ bytes, int start, int count, Encoding/*!*/ encoding) {
+            var decoder = encoding.GetDecoder();
+            var fallback = new CheckDecoderFallback();
+            decoder.Fallback = fallback;
+            decoder.GetCharCount(bytes, start, count, true);
+            return fallback.HasInvalidCharacters;
+        }
+
+        internal static bool ContainsInvalidCharacters(char[]/*!*/ chars, int start, int count, Encoding/*!*/ encoding) {
+            var encoder = encoding.GetEncoder();
+            var fallback = new CheckEncoderFallback();
+            encoder.Fallback = fallback;
+            encoder.GetByteCount(chars, start, count, true);
+            return fallback.HasInvalidCharacters;
+        }
 #else
         internal static bool ContainsInvalidCharacters(byte[]/*!*/ bytes, int start, int count, Encoding/*!*/ encoding) {
             try {
@@ -1075,10 +1078,10 @@ internal sealed class Buffer : EncoderFallbackBuffer {
                 return false;
             }
         }
-#endif
-    }
-}
-
+#endif
+    }
+}
+
 #if SILVERLIGHT
 namespace System.Diagnostics {
     internal struct Stopwatch {
@@ -1093,4 +1096,4 @@ internal struct Stopwatch {
         }
     }
 }
-#endif
+#endif
