Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
Utilities.cs1158 linesDownload Raw Back to interpreter
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Diagnostics;6using System.Dynamic;7using System.Linq;8using System.Linq.Expressions;9using System.Reflection;10using System.Threading;11 12using AstUtils = System.Management.Automation.Interpreter.Utils;13 14namespace System.Management.Automation.Interpreter15{16    internal static class TypeUtils17    {18        internal static Type GetNonNullableType(this Type type)19        {20            if (IsNullableType(type))21            {22                return type.GetGenericArguments()[0];23            }24 25            return type;26        }27 28        internal static Type GetNullableType(Type type)29        {30            Debug.Assert(type != null, "type cannot be null");31            if (type.IsValueType && !IsNullableType(type))32            {33                return typeof(Nullable<>).MakeGenericType(type);34            }35 36            return type;37        }38 39        internal static bool IsNullableType(Type type)40        {41            return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);42        }43 44        internal static bool IsBool(Type type)45        {46            return GetNonNullableType(type) == typeof(bool);47        }48 49        internal static bool IsNumeric(Type type)50        {51            type = GetNonNullableType(type);52            if (!type.IsEnum)53            {54                switch (type.GetTypeCode())55                {56                    case TypeCode.Char:57                    case TypeCode.SByte:58                    case TypeCode.Byte:59                    case TypeCode.Int16:60                    case TypeCode.Int32:61                    case TypeCode.Int64:62                    case TypeCode.Double:63                    case TypeCode.Single:64                    case TypeCode.UInt16:65                    case TypeCode.UInt32:66                    case TypeCode.UInt64:67                        return true;68                }69            }70 71            return false;72        }73 74        internal static bool IsNumeric(TypeCode typeCode)75        {76            switch (typeCode)77            {78                case TypeCode.Char:79                case TypeCode.SByte:80                case TypeCode.Byte:81                case TypeCode.Int16:82                case TypeCode.Int32:83                case TypeCode.Int64:84                case TypeCode.Double:85                case TypeCode.Single:86                case TypeCode.UInt16:87                case TypeCode.UInt32:88                case TypeCode.UInt64:89                    return true;90            }91 92            return false;93        }94 95        internal static bool IsArithmetic(Type type)96        {97            type = GetNonNullableType(type);98            if (!type.IsEnum)99            {100                switch (type.GetTypeCode())101                {102                    case TypeCode.Int16:103                    case TypeCode.Int32:104                    case TypeCode.Int64:105                    case TypeCode.Double:106                    case TypeCode.Single:107                    case TypeCode.UInt16:108                    case TypeCode.UInt32:109                    case TypeCode.UInt64:110                        return true;111                }112            }113 114            return false;115        }116    }117 118    internal static class ArrayUtils119    {120        internal static T[] AddLast<T>(this IList<T> list, T item)121        {122            T[] res = new T[list.Count + 1];123            list.CopyTo(res, 0);124            res[list.Count] = item;125            return res;126        }127    }128 129    internal static class DelegateHelpers130    {131        #region Generated Maximum Delegate Arity132 133        // *** BEGIN GENERATED CODE ***134        // generated by function: gen_max_delegate_arity from: generate_dynsites.py135 136        private const int MaximumArity = 17;137 138        // *** END GENERATED CODE ***139 140        #endregion141 142        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]143        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]144        internal static Type MakeDelegate(Type[] types)145        {146            Debug.Assert(types != null && types.Length > 0);147 148            // Can only used predefined delegates if we have no byref types and149            // the arity is small enough to fit in Func<...> or Action<...>150            if (types.Length > MaximumArity || types.Any(static t => t.IsByRef))151            {152                throw Assert.Unreachable;153                // return MakeCustomDelegate(types);154            }155 156            Type returnType = types[types.Length - 1];157            if (returnType == typeof(void))158            {159                Array.Resize(ref types, types.Length - 1);160                switch (types.Length)161                {162                    case 0: return typeof(Action);163                    #region Generated Delegate Action Types164 165                    // *** BEGIN GENERATED CODE ***166                    // generated by function: gen_delegate_action from: generate_dynsites.py167 168                    case 1: return typeof(Action<>).MakeGenericType(types);169                    case 2: return typeof(Action<,>).MakeGenericType(types);170                    case 3: return typeof(Action<,,>).MakeGenericType(types);171                    case 4: return typeof(Action<,,,>).MakeGenericType(types);172                    case 5: return typeof(Action<,,,,>).MakeGenericType(types);173                    case 6: return typeof(Action<,,,,,>).MakeGenericType(types);174                    case 7: return typeof(Action<,,,,,,>).MakeGenericType(types);175                    case 8: return typeof(Action<,,,,,,,>).MakeGenericType(types);176                    case 9: return typeof(Action<,,,,,,,,>).MakeGenericType(types);177                    case 10: return typeof(Action<,,,,,,,,,>).MakeGenericType(types);178                    case 11: return typeof(Action<,,,,,,,,,,>).MakeGenericType(types);179                    case 12: return typeof(Action<,,,,,,,,,,,>).MakeGenericType(types);180                    case 13: return typeof(Action<,,,,,,,,,,,,>).MakeGenericType(types);181                    case 14: return typeof(Action<,,,,,,,,,,,,,>).MakeGenericType(types);182                    case 15: return typeof(Action<,,,,,,,,,,,,,,>).MakeGenericType(types);183                    case 16: return typeof(Action<,,,,,,,,,,,,,,,>).MakeGenericType(types);184 185                        // *** END GENERATED CODE ***186 187                        #endregion188                }189            }190            else191            {192                switch (types.Length)193                {194                    #region Generated Delegate Func Types195 196                    // *** BEGIN GENERATED CODE ***197                    // generated by function: gen_delegate_func from: generate_dynsites.py198 199                    case 1: return typeof(Func<>).MakeGenericType(types);200                    case 2: return typeof(Func<,>).MakeGenericType(types);201                    case 3: return typeof(Func<,,>).MakeGenericType(types);202                    case 4: return typeof(Func<,,,>).MakeGenericType(types);203                    case 5: return typeof(Func<,,,,>).MakeGenericType(types);204                    case 6: return typeof(Func<,,,,,>).MakeGenericType(types);205                    case 7: return typeof(Func<,,,,,,>).MakeGenericType(types);206                    case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types);207                    case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types);208                    case 10: return typeof(Func<,,,,,,,,,>).MakeGenericType(types);209                    case 11: return typeof(Func<,,,,,,,,,,>).MakeGenericType(types);210                    case 12: return typeof(Func<,,,,,,,,,,,>).MakeGenericType(types);211                    case 13: return typeof(Func<,,,,,,,,,,,,>).MakeGenericType(types);212                    case 14: return typeof(Func<,,,,,,,,,,,,,>).MakeGenericType(types);213                    case 15: return typeof(Func<,,,,,,,,,,,,,,>).MakeGenericType(types);214                    case 16: return typeof(Func<,,,,,,,,,,,,,,,>).MakeGenericType(types);215                    case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types);216 217                        // *** END GENERATED CODE ***218 219                        #endregion220                }221            }222 223            throw Assert.Unreachable;224        }225    }226 227    internal static class ScriptingRuntimeHelpers228    {229        internal static object Int32ToObject(int i)230        {231            return i;232        }233 234        internal static object BooleanToObject(bool b)235        {236            return b ? True : False;237        }238 239        internal static readonly MethodInfo BooleanToObjectMethod = typeof(ScriptingRuntimeHelpers).GetMethod("BooleanToObject");240        internal static readonly MethodInfo Int32ToObjectMethod = typeof(ScriptingRuntimeHelpers).GetMethod("Int32ToObject");241 242        internal static readonly object True = true;243        internal static readonly object False = false;244 245        internal static object GetPrimitiveDefaultValue(Type type)246        {247            switch (type.GetTypeCode())248            {249                case TypeCode.Boolean: return ScriptingRuntimeHelpers.False;250                case TypeCode.SByte: return default(sbyte);251                case TypeCode.Byte: return default(byte);252                case TypeCode.Char: return default(char);253                case TypeCode.Int16: return default(Int16);254                case TypeCode.Int32: return ScriptingRuntimeHelpers.Int32ToObject(0);255                case TypeCode.Int64: return default(Int64);256                case TypeCode.UInt16: return default(UInt16);257                case TypeCode.UInt32: return default(UInt32);258                case TypeCode.UInt64: return default(UInt64);259                case TypeCode.Single: return default(Single);260                case TypeCode.Double: return default(double);261                case TypeCode.DateTime: return default(DateTime);262                case TypeCode.Decimal: return default(Decimal);263                // TypeCode.Empty:  null;264                // TypeCode.Object: default(object) == null;265                // TypeCode.DBNull: default(DBNull) == null;266                // TypeCode.String: default(string) == null;267                default: return null;268            }269        }270    }271 272    /// <summary>273    /// Wraps all arguments passed to a dynamic site with more arguments than can be accepted by a Func/Action delegate.274    /// The binder generating a rule for such a site should unwrap the arguments first and then perform a binding to them.275    /// </summary>276    internal sealed class ArgumentArray277    {278        private readonly object[] _arguments;279 280        // the index of the first item _arguments that represents an argument:281        private readonly int _first;282 283        // the number of items in _arguments that represent the arguments:284 285        internal ArgumentArray(object[] arguments, int first, int count)286        {287            _arguments = arguments;288            _first = first;289            Count = count;290        }291 292        public int Count { get; }293 294        public object GetArgument(int index)295        {296            // ContractUtils.RequiresArrayIndex(_arguments, index, "index");297            return _arguments[_first + index];298        }299 300        public DynamicMetaObject GetMetaObject(Expression parameter, int index)301        {302            return DynamicMetaObject.Create(303                GetArgument(index),304                Expression.Call(305                    s_getArgMethod,306                    AstUtils.Convert(parameter, typeof(ArgumentArray)),307                    AstUtils.Constant(index)308                )309            );310        }311 312        // [CLSCompliant(false)]313        public static object GetArg(ArgumentArray array, int index)314        {315            return array._arguments[array._first + index];316        }317 318        private static readonly MethodInfo s_getArgMethod = new Func<ArgumentArray, int, object>(GetArg).GetMethodInfo();319    }320 321    internal static class ExceptionHelpers322    {323        private const string prevStackTraces = "PreviousStackTraces";324 325        /// <summary>326        /// Updates an exception before it's getting re-thrown so327        /// we can present a reasonable stack trace to the user.328        /// </summary>329        public static Exception UpdateForRethrow(Exception rethrow)330        {331#if !SILVERLIGHT332            List<StackTrace> prev;333 334            // we don't have any dynamic stack trace data, capture the data we can335            // from the raw exception object.336            StackTrace st = new StackTrace(rethrow, true);337 338            if (!TryGetAssociatedStackTraces(rethrow, out prev))339            {340                prev = new List<StackTrace>();341                AssociateStackTraces(rethrow, prev);342            }343 344            prev.Add(st);345#endif346            return rethrow;347        }348 349        /// <summary>350        /// Returns all the stack traces associates with an exception.351        /// </summary>352        public static IList<StackTrace> GetExceptionStackTraces(Exception rethrow)353        {354            List<StackTrace> result;355            return TryGetAssociatedStackTraces(rethrow, out result) ? result : null;356        }357 358        private static void AssociateStackTraces(Exception e, List<StackTrace> traces)359        {360            e.Data[prevStackTraces] = traces;361        }362 363        private static bool TryGetAssociatedStackTraces(Exception e, out List<StackTrace> traces)364        {365            traces = e.Data[prevStackTraces] as List<StackTrace>;366            return traces != null;367        }368    }369 370    /// <summary>371    /// A hybrid dictionary which compares based upon object identity.372    /// </summary>373    internal class HybridReferenceDictionary<TKey, TValue> where TKey : class374    {375        private KeyValuePair<TKey, TValue>[] _keysAndValues;376        private Dictionary<TKey, TValue> _dict;377        private int _count;378 379        private const int _arraySize = 10;380 381        public HybridReferenceDictionary()382        {383        }384 385        public HybridReferenceDictionary(int initialCapacity)386        {387            if (initialCapacity > _arraySize)388            {389                _dict = new Dictionary<TKey, TValue>(initialCapacity);390            }391            else392            {393                _keysAndValues = new KeyValuePair<TKey, TValue>[initialCapacity];394            }395        }396 397        public bool TryGetValue(TKey key, out TValue value)398        {399            Debug.Assert(key != null);400 401            if (_dict != null)402            {403                return _dict.TryGetValue(key, out value);404            }405            else if (_keysAndValues != null)406            {407                for (int i = 0; i < _keysAndValues.Length; i++)408                {409                    if (_keysAndValues[i].Key == key)410                    {411                        value = _keysAndValues[i].Value;412                        return true;413                    }414                }415            }416 417            value = default(TValue);418            return false;419        }420 421        public bool Remove(TKey key)422        {423            Debug.Assert(key != null);424 425            if (_dict != null)426            {427                return _dict.Remove(key);428            }429            else if (_keysAndValues != null)430            {431                for (int i = 0; i < _keysAndValues.Length; i++)432                {433                    if (_keysAndValues[i].Key == key)434                    {435                        _keysAndValues[i] = new KeyValuePair<TKey, TValue>();436                        _count--;437                        return true;438                    }439                }440            }441 442            return false;443        }444 445        public bool ContainsKey(TKey key)446        {447            Debug.Assert(key != null);448 449            if (_dict != null)450            {451                return _dict.ContainsKey(key);452            }453            else if (_keysAndValues != null)454            {455                for (int i = 0; i < _keysAndValues.Length; i++)456                {457                    if (_keysAndValues[i].Key == key)458                    {459                        return true;460                    }461                }462            }463 464            return false;465        }466 467        public int Count468        {469            get470            {471                if (_dict != null)472                {473                    return _dict.Count;474                }475 476                return _count;477            }478        }479 480        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()481        {482            if (_dict != null)483            {484                return _dict.GetEnumerator();485            }486 487            return GetEnumeratorWorker();488        }489 490        private IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorWorker()491        {492            if (_keysAndValues != null)493            {494                for (int i = 0; i < _keysAndValues.Length; i++)495                {496                    if (_keysAndValues[i].Key != null)497                    {498                        yield return _keysAndValues[i];499                    }500                }501            }502        }503 504        public TValue this[TKey key]505        {506            get507            {508                Debug.Assert(key != null);509 510                TValue res;511                if (TryGetValue(key, out res))512                {513                    return res;514                }515 516                throw new KeyNotFoundException();517            }518 519            set520            {521                Debug.Assert(key != null);522 523                if (_dict != null)524                {525                    _dict[key] = value;526                }527                else528                {529                    int index;530                    if (_keysAndValues != null)531                    {532                        index = -1;533                        for (int i = 0; i < _keysAndValues.Length; i++)534                        {535                            if (_keysAndValues[i].Key == key)536                            {537                                _keysAndValues[i] = new KeyValuePair<TKey, TValue>(key, value);538                                return;539                            }540                            else if (_keysAndValues[i].Key == null)541                            {542                                index = i;543                            }544                        }545                    }546                    else547                    {548                        _keysAndValues = new KeyValuePair<TKey, TValue>[_arraySize];549                        index = 0;550                    }551 552                    if (index != -1)553                    {554                        _count++;555                        _keysAndValues[index] = new KeyValuePair<TKey, TValue>(key, value);556                    }557                    else558                    {559                        _dict = new Dictionary<TKey, TValue>();560                        for (int i = 0; i < _keysAndValues.Length; i++)561                        {562                            _dict[_keysAndValues[i].Key] = _keysAndValues[i].Value;563                        }564 565                        _keysAndValues = null;566 567                        _dict[key] = value;568                    }569                }570            }571        }572    }573 574    /// <summary>575    /// Provides a dictionary-like object used for caches which holds onto a maximum576    /// number of elements specified at construction time.577    ///578    /// This class is not thread safe.579    /// </summary>580    internal class CacheDict<TKey, TValue>581    {582        private readonly Dictionary<TKey, KeyInfo> _dict = new Dictionary<TKey, KeyInfo>();583        private readonly LinkedList<TKey> _list = new LinkedList<TKey>();584        private readonly int _maxSize;585 586        /// <summary>587        /// Creates a dictionary-like object used for caches.588        /// </summary>589        /// <param name="maxSize">The maximum number of elements to store.</param>590        public CacheDict(int maxSize)591        {592            _maxSize = maxSize;593        }594 595        /// <summary>596        /// Tries to get the value associated with 'key', returning true if it's found and597        /// false if it's not present.598        /// </summary>599        public bool TryGetValue(TKey key, out TValue value)600        {601            KeyInfo storedValue;602            if (_dict.TryGetValue(key, out storedValue))603            {604                LinkedListNode<TKey> node = storedValue.List;605                if (node.Previous != null)606                {607                    // move us to the head of the list...608                    _list.Remove(node);609                    _list.AddFirst(node);610                }611 612                value = storedValue.Value;613                return true;614            }615 616            value = default(TValue);617            return false;618        }619 620        /// <summary>621        /// Adds a new element to the cache, replacing and moving it to the front if the622        /// element is already present.623        /// </summary>624        public void Add(TKey key, TValue value)625        {626            KeyInfo keyInfo;627            if (_dict.TryGetValue(key, out keyInfo))628            {629                // remove original entry from the linked list630                _list.Remove(keyInfo.List);631            }632            else if (_list.Count == _maxSize)633            {634                // we've reached capacity, remove the last used element...635                LinkedListNode<TKey> node = _list.Last;636                _list.RemoveLast();637                bool res = _dict.Remove(node.Value);638                Debug.Assert(res);639            }640 641            // add the new entry to the head of the list and into the dictionary642            LinkedListNode<TKey> listNode = new LinkedListNode<TKey>(key);643            _list.AddFirst(listNode);644            _dict[key] = new CacheDict<TKey, TValue>.KeyInfo(value, listNode);645        }646 647        /// <summary>648        /// Returns the value associated with the given key, or throws KeyNotFoundException649        /// if the key is not present.650        /// </summary>651        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]652        public TValue this[TKey key]653        {654            get655            {656                TValue res;657                if (TryGetValue(key, out res))658                {659                    return res;660                }661 662                throw new KeyNotFoundException();663            }664 665            set666            {667                Add(key, value);668            }669        }670 671        private readonly struct KeyInfo672        {673            internal readonly TValue Value;674            internal readonly LinkedListNode<TKey> List;675 676            internal KeyInfo(TValue value, LinkedListNode<TKey> list)677            {678                Value = value;679                List = list;680            }681        }682    }683 684    internal class ThreadLocal<T>685    {686        private StorageInfo[] _stores;                                         // array of storage indexed by managed thread ID687        private static readonly StorageInfo[] s_updating = Array.Empty<StorageInfo>();   // a marker used when updating the array688        private readonly bool _refCounted;689 690        public ThreadLocal()691        {692        }693 694        /// <summary>695        /// True if the caller will guarantee that all cleanup happens as the thread696        /// unwinds.697        ///698        /// This is typically used in a case where the thread local is surrounded by699        /// a try/finally block.  The try block pushes some state, the finally block700        /// restores the previous state.  Therefore when the thread exits the thread701        /// local is back to it's original state.  This allows the ThreadLocal object702        /// to not check the current owning thread on retrieval.703        /// </summary>704        public ThreadLocal(bool refCounted)705        {706            _refCounted = refCounted;707        }708 709        #region Public API710 711        /// <summary>712        /// Gets or sets the value for the current thread.713        /// </summary>714        public T Value715        {716            get717            {718                return GetStorageInfo().Value;719            }720 721            set722            {723                GetStorageInfo().Value = value;724            }725        }726 727        /// <summary>728        /// Gets the current value if its not == null or calls the provided function729        /// to create a new value.730        /// </summary>731        public T GetOrCreate(Func<T> func)732        {733            Assert.NotNull(func);734 735            StorageInfo si = GetStorageInfo();736            T res = si.Value;737            if (res == null)738            {739                si.Value = res = func();740            }741 742            return res;743        }744 745        /// <summary>746        /// Calls the provided update function with the current value and747        /// replaces the current value with the result of the function.748        /// </summary>749        public T Update(Func<T, T> updater)750        {751            Assert.NotNull(updater);752 753            StorageInfo si = GetStorageInfo();754            return si.Value = updater(si.Value);755        }756 757        /// <summary>758        /// Replaces the current value with a new one and returns the old value.759        /// </summary>760        public T Update(T newValue)761        {762            StorageInfo si = GetStorageInfo();763            var oldValue = si.Value;764            si.Value = newValue;765            return oldValue;766        }767 768        #endregion769 770        #region Storage implementation771 772        /// <summary>773        /// Gets the StorageInfo for the current thread.774        /// </summary>775        public StorageInfo GetStorageInfo()776        {777            return GetStorageInfo(_stores);778        }779 780        private StorageInfo GetStorageInfo(StorageInfo[] curStorage)781        {782            int threadId = Environment.CurrentManagedThreadId;783 784            // fast path if we already have a value in the array785            if (curStorage != null && curStorage.Length > threadId)786            {787                StorageInfo res = curStorage[threadId];788 789                if (res != null && (_refCounted || res.Thread == Thread.CurrentThread))790                {791                    return res;792                }793            }794 795            return RetryOrCreateStorageInfo(curStorage);796        }797 798        /// <summary>799        /// Called when the fast path storage lookup fails. if we encountered the Empty storage800        /// during the initial fast check then spin until we hit non-empty storage and try the fast801        /// path again.802        /// </summary>803        private StorageInfo RetryOrCreateStorageInfo(StorageInfo[] curStorage)804        {805            if (curStorage == s_updating)806            {807                // we need to retry808                while ((curStorage = _stores) == s_updating)809                {810                    Thread.Sleep(0);811                }812 813                // we now have a non-empty storage info to retry with814                return GetStorageInfo(curStorage);815            }816 817            // we need to mutate the StorageInfo[] array or create a new StorageInfo818            return CreateStorageInfo();819        }820 821        /// <summary>822        /// Creates the StorageInfo for the thread when one isn't already present.823        /// </summary>824        private StorageInfo CreateStorageInfo()825        {826            // we do our own locking, tell hosts this is a bad time to interrupt us.827            Thread.BeginCriticalRegion();828 829            StorageInfo[] curStorage = s_updating;830            try831            {832                int threadId = Environment.CurrentManagedThreadId;833                StorageInfo newInfo = new StorageInfo(Thread.CurrentThread);834 835                // set to updating while potentially resizing/mutating, then we'll836                // set back to the current value.837                while ((curStorage = Interlocked.Exchange(ref _stores, s_updating)) == s_updating)838                {839                    // another thread is already updating...840                    Thread.Sleep(0);841                }842 843                // check and make sure we have a space in the array for our value844                if (curStorage == null)845                {846                    curStorage = new StorageInfo[threadId + 1];847                }848                else if (curStorage.Length <= threadId)849                {850                    StorageInfo[] newStorage = new StorageInfo[threadId + 1];851                    for (int i = 0; i < curStorage.Length; i++)852                    {853                        // leave out the threads that have exited854                        if (curStorage[i] != null && curStorage[i].Thread.IsAlive)855                        {856                            newStorage[i] = curStorage[i];857                        }858                    }859 860                    curStorage = newStorage;861                }862 863                // create our StorageInfo in the array, the empty check ensures we're only here864                // when we need to create.865                Debug.Assert(curStorage[threadId] == null || curStorage[threadId].Thread != Thread.CurrentThread);866 867                return curStorage[threadId] = newInfo;868            }869            finally870            {871                if (curStorage != s_updating)872                {873                    // let others access the storage again874                    Interlocked.Exchange(ref _stores, curStorage);875                }876 877                Thread.EndCriticalRegion();878            }879        }880 881        /// <summary>882        /// Helper class for storing the value.  We need to track if a ManagedThreadId883        /// has been re-used so we also store the thread which owns the value.884        /// </summary>885        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] // TODO886        internal sealed class StorageInfo887        {888            internal readonly Thread Thread;                 // the thread that owns the StorageInfo889            public T Value;                                // the current value for the owning thread890 891            internal StorageInfo(Thread curThread)892            {893                Assert.NotNull(curThread);894 895                Thread = curThread;896            }897        }898 899        #endregion900    }901 902    internal static class Assert903    {904        internal static Exception Unreachable905        {906            get907            {908                Debug.Fail("Unreachable");909                return new InvalidOperationException("Code supposed to be unreachable");910            }911        }912 913        [Conditional("DEBUG")]914        public static void NotNull(object var)915        {916            Debug.Assert(var != null);917        }918 919        [Conditional("DEBUG")]920        public static void NotNull(object var1, object var2)921        {922            Debug.Assert(var1 != null && var2 != null);923        }924 925        [Conditional("DEBUG")]926        public static void NotNull(object var1, object var2, object var3)927        {928            Debug.Assert(var1 != null && var2 != null && var3 != null);929        }930 931        [Conditional("DEBUG")]932        public static void NotNullItems<T>(IEnumerable<T> items) where T : class933        {934            Debug.Assert(items != null);935            foreach (object item in items)936            {937                Debug.Assert(item != null);938            }939        }940 941        [Conditional("DEBUG")]942        public static void NotEmpty(string str)943        {944            Debug.Assert(!string.IsNullOrEmpty(str));945        }946    }947 948    [Flags]949    internal enum ExpressionAccess950    {951        None = 0,952        Read = 1,953        Write = 2,954        ReadWrite = Read | Write,955    }956 957    internal static class Utils958    {959        internal static Expression Constant(object value)960        {961            return Expression.Constant(value);962        }963 964        private static readonly DefaultExpression s_voidInstance = Expression.Empty();965 966        public static DefaultExpression Empty()967        {968            return s_voidInstance;969        }970 971        public static Expression Void(Expression expression)972        {973            // ContractUtils.RequiresNotNull(expression, "expression");974            if (expression.Type == typeof(void))975            {976                return expression;977            }978 979            return Expression.Block(expression, Utils.Empty());980        }981 982        public static DefaultExpression Default(Type type)983        {984            if (type == typeof(void))985            {986                return Empty();987            }988 989            return Expression.Default(type);990        }991 992        public static Expression Convert(Expression expression, Type type)993        {994            // ContractUtils.RequiresNotNull(expression, "expression");995 996            if (expression.Type == type)997            {998                return expression;999            }1000 1001            if (expression.Type == typeof(void))1002            {1003                return Expression.Block(expression, Utils.Default(type));1004            }1005 1006            if (type == typeof(void))1007            {1008                return Void(expression);1009            }1010 1011            // TODO: this is not the right level for this to be at. It should1012            // be pushed into languages if they really want this behavior.1013            if (type == typeof(object))1014            {1015                return Box(expression);1016            }1017 1018            return Expression.Convert(expression, type);1019        }1020 1021        public static Expression Box(Expression expression)1022        {1023            MethodInfo m;1024            if (expression.Type == typeof(int))1025            {1026                m = ScriptingRuntimeHelpers.Int32ToObjectMethod;1027            }1028            else if (expression.Type == typeof(bool))1029            {1030                m = ScriptingRuntimeHelpers.BooleanToObjectMethod;1031            }1032            else1033            {1034                m = null;1035            }1036 1037            return Expression.Convert(expression, typeof(object), m);1038        }1039 1040        public static bool IsReadWriteAssignment(this ExpressionType type)1041        {1042            switch (type)1043            {1044                // unary:1045                case ExpressionType.PostDecrementAssign:1046                case ExpressionType.PostIncrementAssign:1047                case ExpressionType.PreDecrementAssign:1048                case ExpressionType.PreIncrementAssign:1049 1050                // binary - compound:1051                case ExpressionType.AddAssign:1052                case ExpressionType.AddAssignChecked:1053                case ExpressionType.AndAssign:1054                case ExpressionType.DivideAssign:1055                case ExpressionType.ExclusiveOrAssign:1056                case ExpressionType.LeftShiftAssign:1057                case ExpressionType.ModuloAssign:1058                case ExpressionType.MultiplyAssign:1059                case ExpressionType.MultiplyAssignChecked:1060                case ExpressionType.OrAssign:1061                case ExpressionType.PowerAssign:1062                case ExpressionType.RightShiftAssign:1063                case ExpressionType.SubtractAssign:1064                case ExpressionType.SubtractAssignChecked:1065                    return true;1066            }1067 1068            return false;1069        }1070    }1071 1072    internal static class CollectionExtension1073    {1074        internal static bool TrueForAll<T>(this IEnumerable<T> collection, Predicate<T> predicate)1075        {1076            // ContractUtils.RequiresNotNull(collection, "collection");1077            // ContractUtils.RequiresNotNull(predicate, "predicate");1078 1079            foreach (T item in collection)1080            {1081                if (!predicate(item))1082                {1083                    return false;1084                }1085            }1086 1087            return true;1088        }1089 1090        internal static TResult[] Map<TSource, TResult>(this ICollection<TSource> source, Func<TSource, TResult> selector)1091        {1092            int count = source.Count;1093            TResult[] result = new TResult[count];1094            count = 0;1095            foreach (TSource t in source)1096            {1097                result[count++] = selector(t);1098            }1099 1100            return result;1101        }1102 1103        // We could probably improve the hashing here1104        internal static int ListHashCode<T>(this IEnumerable<T> list)1105        {1106            var cmp = EqualityComparer<T>.Default;1107            int h = 6551;1108            foreach (T t in list)1109            {1110                h ^= (h << 5) ^ cmp.GetHashCode(t);1111            }1112 1113            return h;1114        }1115 1116        internal static bool ListEquals<T>(this ICollection<T> first, ICollection<T> second)1117        {1118            if (first.Count != second.Count)1119            {1120                return false;1121            }1122 1123            var cmp = EqualityComparer<T>.Default;1124            var f = first.GetEnumerator();1125            var s = second.GetEnumerator();1126            while (f.MoveNext())1127            {1128                s.MoveNext();1129 1130                if (!cmp.Equals(f.Current, s.Current))1131                {1132                    return false;1133                }1134            }1135 1136            return true;1137        }1138    }1139 1140    internal sealed class ListEqualityComparer<T> : EqualityComparer<ICollection<T>>1141    {1142        internal static readonly ListEqualityComparer<T> Instance = new ListEqualityComparer<T>();1143 1144        private ListEqualityComparer() { }1145 1146        // EqualityComparer<T> handles null and object identity for us1147        public override bool Equals(ICollection<T> x, ICollection<T> y)1148        {1149            return x.ListEquals(y);1150        }1151 1152        public override int GetHashCode(ICollection<T> obj)1153        {1154            return obj.ListHashCode();1155        }1156    }1157}1158