1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections.Generic;
6 using System.Diagnostics;
7 using System.Dynamic.Utils;
8 using System.Reflection;
9 using System.Runtime.ExceptionServices;
10 
11 namespace System.Linq.Expressions.Interpreter
12 {
13 #if FEATURE_MAKE_RUN_METHODS
14     internal static partial class DelegateHelpers
15     {
16         private const int MaximumArity = 17;
17 
18         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
19         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]
MakeDelegate(Type[] types)20         internal static Type MakeDelegate(Type[] types)
21         {
22             Debug.Assert(types != null && types.Length > 0);
23 
24             // Can only used predefined delegates if we have no byref types and
25             // the arity is small enough to fit in Func<...> or Action<...>
26             if (types.Length > MaximumArity || types.Any(t => t.IsByRef))
27             {
28                 throw ContractUtils.Unreachable;
29             }
30 
31             Type returnType = types[types.Length - 1];
32             if (returnType == typeof(void))
33             {
34                 Array.Resize(ref types, types.Length - 1);
35                 switch (types.Length)
36                 {
37                     case 0: return typeof(Action);
38 
39                     case 1: return typeof(Action<>).MakeGenericType(types);
40                     case 2: return typeof(Action<,>).MakeGenericType(types);
41                     case 3: return typeof(Action<,,>).MakeGenericType(types);
42                     case 4: return typeof(Action<,,,>).MakeGenericType(types);
43                     case 5: return typeof(Action<,,,,>).MakeGenericType(types);
44                     case 6: return typeof(Action<,,,,,>).MakeGenericType(types);
45                     case 7: return typeof(Action<,,,,,,>).MakeGenericType(types);
46                     case 8: return typeof(Action<,,,,,,,>).MakeGenericType(types);
47                     case 9: return typeof(Action<,,,,,,,,>).MakeGenericType(types);
48                     case 10: return typeof(Action<,,,,,,,,,>).MakeGenericType(types);
49                     case 11: return typeof(Action<,,,,,,,,,,>).MakeGenericType(types);
50                     case 12: return typeof(Action<,,,,,,,,,,,>).MakeGenericType(types);
51                     case 13: return typeof(Action<,,,,,,,,,,,,>).MakeGenericType(types);
52                     case 14: return typeof(Action<,,,,,,,,,,,,,>).MakeGenericType(types);
53                     case 15: return typeof(Action<,,,,,,,,,,,,,,>).MakeGenericType(types);
54                     case 16: return typeof(Action<,,,,,,,,,,,,,,,>).MakeGenericType(types);
55                 }
56             }
57             else
58             {
59                 switch (types.Length)
60                 {
61                     case 1: return typeof(Func<>).MakeGenericType(types);
62                     case 2: return typeof(Func<,>).MakeGenericType(types);
63                     case 3: return typeof(Func<,,>).MakeGenericType(types);
64                     case 4: return typeof(Func<,,,>).MakeGenericType(types);
65                     case 5: return typeof(Func<,,,,>).MakeGenericType(types);
66                     case 6: return typeof(Func<,,,,,>).MakeGenericType(types);
67                     case 7: return typeof(Func<,,,,,,>).MakeGenericType(types);
68                     case 8: return typeof(Func<,,,,,,,>).MakeGenericType(types);
69                     case 9: return typeof(Func<,,,,,,,,>).MakeGenericType(types);
70                     case 10: return typeof(Func<,,,,,,,,,>).MakeGenericType(types);
71                     case 11: return typeof(Func<,,,,,,,,,,>).MakeGenericType(types);
72                     case 12: return typeof(Func<,,,,,,,,,,,>).MakeGenericType(types);
73                     case 13: return typeof(Func<,,,,,,,,,,,,>).MakeGenericType(types);
74                     case 14: return typeof(Func<,,,,,,,,,,,,,>).MakeGenericType(types);
75                     case 15: return typeof(Func<,,,,,,,,,,,,,,>).MakeGenericType(types);
76                     case 16: return typeof(Func<,,,,,,,,,,,,,,,>).MakeGenericType(types);
77                     case 17: return typeof(Func<,,,,,,,,,,,,,,,,>).MakeGenericType(types);
78                 }
79             }
80             throw ContractUtils.Unreachable;
81         }
82     }
83 #endif
84 
85     internal static class ScriptingRuntimeHelpers
86     {
Int32ToObject(int i)87         public static object Int32ToObject(int i)
88         {
89             switch (i)
90             {
91                 case -1:
92                     return Utils.BoxedIntM1;
93                 case 0:
94                     return Utils.BoxedInt0;
95                 case 1:
96                     return Utils.BoxedInt1;
97                 case 2:
98                     return Utils.BoxedInt2;
99                 case 3:
100                     return Utils.BoxedInt3;
101             }
102 
103             return i;
104         }
105 
GetPrimitiveDefaultValue(Type type)106         internal static object GetPrimitiveDefaultValue(Type type)
107         {
108             object result;
109 
110             switch (type.GetTypeCode())
111             {
112                 case TypeCode.Boolean:
113                     result = Utils.BoxedFalse;
114                     break;
115                 case TypeCode.SByte:
116                     result = Utils.BoxedDefaultSByte;
117                     break;
118                 case TypeCode.Byte:
119                     result = Utils.BoxedDefaultByte;
120                     break;
121                 case TypeCode.Char:
122                     result = Utils.BoxedDefaultChar;
123                     break;
124                 case TypeCode.Int16:
125                     result = Utils.BoxedDefaultInt16;
126                     break;
127                 case TypeCode.Int32:
128                     result = Utils.BoxedInt0;
129                     break;
130                 case TypeCode.Int64:
131                     result = Utils.BoxedDefaultInt64;
132                     break;
133                 case TypeCode.UInt16:
134                     result = Utils.BoxedDefaultUInt16;
135                     break;
136                 case TypeCode.UInt32:
137                     result = Utils.BoxedDefaultUInt32;
138                     break;
139                 case TypeCode.UInt64:
140                     result = Utils.BoxedDefaultUInt64;
141                     break;
142                 case TypeCode.Single:
143                     return Utils.BoxedDefaultSingle;
144                 case TypeCode.Double:
145                     return Utils.BoxedDefaultDouble;
146                 case TypeCode.DateTime:
147                     return Utils.BoxedDefaultDateTime;
148                 case TypeCode.Decimal:
149                     return Utils.BoxedDefaultDecimal;
150                 default:
151                     // Also covers DBNull which is a class.
152                     return null;
153             }
154 
155             if (type.IsEnum)
156             {
157                 result = Enum.ToObject(type, result);
158             }
159 
160             return result;
161         }
162     }
163 
164     internal static class ExceptionHelpers
165     {
166         /// <summary>
167         /// Updates an exception before it's getting re-thrown so
168         /// we can present a reasonable stack trace to the user.
169         /// </summary>
UnwrapAndRethrow(TargetInvocationException exception)170         public static void UnwrapAndRethrow(TargetInvocationException exception)
171         {
172             ExceptionDispatchInfo.Throw(exception.InnerException);
173         }
174     }
175 
176     /// <summary>
177     /// A hybrid dictionary which compares based upon object identity.
178     /// </summary>
179     internal class HybridReferenceDictionary<TKey, TValue> where TKey : class
180     {
181         private KeyValuePair<TKey, TValue>[] _keysAndValues;
182         private Dictionary<TKey, TValue> _dict;
183         private const int ArraySize = 10;
184 
TryGetValue(TKey key, out TValue value)185         public bool TryGetValue(TKey key, out TValue value)
186         {
187             Debug.Assert(key != null);
188 
189             if (_dict != null)
190             {
191                 return _dict.TryGetValue(key, out value);
192             }
193             else if (_keysAndValues != null)
194             {
195                 for (int i = 0; i < _keysAndValues.Length; i++)
196                 {
197                     if (_keysAndValues[i].Key == key)
198                     {
199                         value = _keysAndValues[i].Value;
200                         return true;
201                     }
202                 }
203             }
204             value = default(TValue);
205             return false;
206         }
207 
Remove(TKey key)208         public void Remove(TKey key)
209         {
210             Debug.Assert(key != null);
211 
212             if (_dict != null)
213             {
214                 _dict.Remove(key);
215             }
216             else if (_keysAndValues != null)
217             {
218                 for (int i = 0; i < _keysAndValues.Length; i++)
219                 {
220                     if (_keysAndValues[i].Key == key)
221                     {
222                         _keysAndValues[i] = new KeyValuePair<TKey, TValue>();
223                         return;
224                     }
225                 }
226             }
227         }
228 
ContainsKey(TKey key)229         public bool ContainsKey(TKey key)
230         {
231             Debug.Assert(key != null);
232 
233             if (_dict != null)
234             {
235                 return _dict.ContainsKey(key);
236             }
237 
238             KeyValuePair<TKey, TValue>[] keysAndValues = _keysAndValues;
239             if (keysAndValues != null)
240             {
241                 for (int i = 0; i < keysAndValues.Length; i++)
242                 {
243                     if (keysAndValues[i].Key == key)
244                     {
245                         return true;
246                     }
247                 }
248             }
249 
250             return false;
251         }
252 
GetEnumerator()253         public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
254         {
255             if (_dict != null)
256             {
257                 return _dict.GetEnumerator();
258             }
259 
260             return GetEnumeratorWorker();
261         }
262 
GetEnumeratorWorker()263         private IEnumerator<KeyValuePair<TKey, TValue>> GetEnumeratorWorker()
264         {
265             if (_keysAndValues != null)
266             {
267                 for (int i = 0; i < _keysAndValues.Length; i++)
268                 {
269                     if (_keysAndValues[i].Key != null)
270                     {
271                         yield return _keysAndValues[i];
272                     }
273                 }
274             }
275         }
276 
277         public TValue this[TKey key]
278         {
279             get
280             {
281                 Debug.Assert(key != null);
282 
283                 TValue res;
284                 if (TryGetValue(key, out res))
285                 {
286                     return res;
287                 }
288 
289                 throw new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key.ToString()));
290             }
291             set
292             {
293                 Debug.Assert(key != null);
294 
295                 if (_dict != null)
296                 {
297                     _dict[key] = value;
298                 }
299                 else
300                 {
301                     int index;
302                     if (_keysAndValues != null)
303                     {
304                         index = -1;
305                         for (int i = 0; i < _keysAndValues.Length; i++)
306                         {
307                             if (_keysAndValues[i].Key == key)
308                             {
309                                 _keysAndValues[i] = new KeyValuePair<TKey, TValue>(key, value);
310                                 return;
311                             }
312                             else if (_keysAndValues[i].Key == null)
313                             {
314                                 index = i;
315                             }
316                         }
317                     }
318                     else
319                     {
320                         _keysAndValues = new KeyValuePair<TKey, TValue>[ArraySize];
321                         index = 0;
322                     }
323 
324                     if (index != -1)
325                     {
326                         _keysAndValues[index] = new KeyValuePair<TKey, TValue>(key, value);
327                     }
328                     else
329                     {
330                         _dict = new Dictionary<TKey, TValue>();
331                         for (int i = 0; i < _keysAndValues.Length; i++)
332                         {
333                             _dict[_keysAndValues[i].Key] = _keysAndValues[i].Value;
334                         }
335                         _keysAndValues = null;
336 
337                         _dict[key] = value;
338                     }
339                 }
340             }
341         }
342     }
343 
344     internal static class Assert
345     {
346         [Conditional("DEBUG")]
NotNull(object var)347         public static void NotNull(object var)
348         {
349             Debug.Assert(var != null);
350         }
351     }
352 }
353