PageRenderTime 46ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Boo.Lang/Runtime/RuntimeServices.cs

http://github.com/bamboo/boo
C# | 1770 lines | 1480 code | 214 blank | 76 comment | 269 complexity | d47b37c8470aa60fc303842dc3f679b3 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. #region license
  2. // Copyright (c) 2004, 2007 Rodrigo B. de Oliveira (rbo@acm.org)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Rodrigo B. de Oliveira nor the names of its
  14. // contributors may be used to endorse or promote products derived from this
  15. // software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  21. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #endregion
  28. using System;
  29. using System.Collections.Generic;
  30. using System.Diagnostics;
  31. using System.Reflection;
  32. using System.Collections;
  33. using System.IO;
  34. using System.Text;
  35. using Boo.Lang.Resources;
  36. using Boo.Lang.Runtime.DynamicDispatching;
  37. namespace Boo.Lang.Runtime
  38. {
  39. public class RuntimeServices
  40. {
  41. private static readonly object[] NoArguments = new object[0];
  42. private static readonly Type RuntimeServicesType = typeof(RuntimeServices);
  43. internal const BindingFlags InstanceMemberFlags = BindingFlags.Public |
  44. BindingFlags.NonPublic |
  45. BindingFlags.Instance;
  46. internal const BindingFlags DefaultBindingFlags = InstanceMemberFlags |
  47. BindingFlags.OptionalParamBinding |
  48. BindingFlags.Static |
  49. BindingFlags.FlattenHierarchy;
  50. private const BindingFlags InvokeBindingFlags = DefaultBindingFlags |
  51. BindingFlags.InvokeMethod;
  52. private const BindingFlags SetPropertyBindingFlags = DefaultBindingFlags |
  53. BindingFlags.SetProperty |
  54. BindingFlags.SetField;
  55. private const BindingFlags GetPropertyBindingFlags = DefaultBindingFlags |
  56. BindingFlags.GetProperty |
  57. BindingFlags.GetField;
  58. private static readonly DispatcherCache _cache = new DispatcherCache();
  59. private static readonly ExtensionRegistry _extensions = new ExtensionRegistry();
  60. public delegate void CodeBlock();
  61. public static void WithExtensions(Type extensions, CodeBlock block)
  62. {
  63. RegisterExtensions(extensions);
  64. try
  65. {
  66. block();
  67. }
  68. finally
  69. {
  70. UnRegisterExtensions(extensions);
  71. }
  72. }
  73. public static void RegisterExtensions(Type extensions)
  74. {
  75. _extensions.Register(extensions);
  76. }
  77. public static void UnRegisterExtensions(Type extensions)
  78. {
  79. _extensions.UnRegister(extensions);
  80. }
  81. public static object Invoke(object target, string name, object[] args)
  82. {
  83. var dispatcher = GetDispatcher(target, args, name, () => CreateMethodDispatcher(target, name, args));
  84. return dispatcher(target, args);
  85. }
  86. private static Dispatcher CreateMethodDispatcher(object target, string name, object[] args)
  87. {
  88. var duck = target as IQuackFu;
  89. if (null != duck)
  90. return (o, arguments) => ((IQuackFu) o).QuackInvoke(name, arguments);
  91. var type = target as Type;
  92. if (null != type)
  93. // static method
  94. return DoCreateMethodDispatcher(null, type, name, args);
  95. var targetType = target.GetType();
  96. if (targetType.IsCOMObject)
  97. {
  98. // COM methods cant be seen through reflection
  99. // so maybe the proper way to support parameter conversions
  100. // is indeed by creating a specific Binder object
  101. // which knows the boo conversion rules
  102. return
  103. (o, arguments) => o.GetType().InvokeMember(name, InvokeBindingFlags, null, target, arguments);
  104. }
  105. return DoCreateMethodDispatcher(target, targetType, name, args);
  106. }
  107. private static Dispatcher DoCreateMethodDispatcher(object target, Type targetType, string name, object[] args)
  108. {
  109. return new MethodDispatcherFactory(_extensions, target, targetType, name, args).Create();
  110. }
  111. private static Dispatcher GetDispatcher(object target, object[] args, string cacheKeyName, DispatcherCache.DispatcherFactory factory)
  112. {
  113. var cacheKeyTypes = MethodResolver.GetArgumentTypes(args);
  114. return GetDispatcher(target, cacheKeyName, cacheKeyTypes, factory);
  115. }
  116. private static Dispatcher GetDispatcher(object target, string cacheKeyName, Type[] cacheKeyTypes, DispatcherCache.DispatcherFactory factory)
  117. {
  118. var targetType = (target as Type) ?? target.GetType();
  119. var key = new DispatcherKey(targetType, cacheKeyName, cacheKeyTypes);
  120. return _cache.Get(key, factory);
  121. }
  122. public static object GetProperty(object target, string name)
  123. {
  124. var dispatcher = GetDispatcher(target, NoArguments, name, () => CreatePropGetDispatcher(target, name));
  125. return dispatcher(target, NoArguments);
  126. }
  127. private static Dispatcher CreatePropGetDispatcher(object target, string name)
  128. {
  129. var duck = target as IQuackFu;
  130. if (null != duck)
  131. return (o, args) => ((IQuackFu) o).QuackGet(name, null);
  132. var type = target as Type;
  133. if (null != type)
  134. return DoCreatePropGetDispatcher(null, type, name);
  135. var targetType = target.GetType();
  136. if (targetType.IsCOMObject)
  137. return (o, args) => o.GetType().InvokeMember(name, GetPropertyBindingFlags, null, o, null);
  138. return DoCreatePropGetDispatcher(target, target.GetType(), name);
  139. }
  140. private static Dispatcher DoCreatePropGetDispatcher(object target, Type type, string name)
  141. {
  142. return new PropertyDispatcherFactory(_extensions, target, type, name).CreateGetter();
  143. }
  144. public static object SetProperty(object target, string name, object value)
  145. {
  146. object[] args = new[] { value };
  147. var dispatcher = GetDispatcher(target, args, name, () => CreatePropSetDispatcher(target, name, value));
  148. return dispatcher(target, args);
  149. }
  150. private static Dispatcher CreatePropSetDispatcher(object target, string name, object value)
  151. {
  152. var duck = target as IQuackFu;
  153. if (null != duck)
  154. return (o, args) => ((IQuackFu) o).QuackSet(name, null, args[0]);
  155. var type = target as Type;
  156. if (null != type)
  157. return DoCreatePropSetDispatcher(null, type, name, value);
  158. var targetType = target.GetType();
  159. if (targetType.IsCOMObject)
  160. return (o, args) => o.GetType().InvokeMember(name, SetPropertyBindingFlags, null, o, args);
  161. return DoCreatePropSetDispatcher(target, targetType, name, value);
  162. }
  163. private static Dispatcher DoCreatePropSetDispatcher(object target, Type type, string name, object value)
  164. {
  165. return new PropertyDispatcherFactory(_extensions, target, type, name, value).CreateSetter();
  166. }
  167. public struct ValueTypeChange
  168. {
  169. public object Target;
  170. public string Member;
  171. public object Value;
  172. public ValueTypeChange(object target, string member, object value)
  173. {
  174. Target = target;
  175. Member = member;
  176. Value = value;
  177. }
  178. }
  179. public static void PropagateValueTypeChanges(ValueTypeChange[] changes)
  180. {
  181. foreach (ValueTypeChange change in changes)
  182. {
  183. if (!(change.Value is ValueType)) break;
  184. try
  185. {
  186. SetProperty(change.Target, change.Member, change.Value);
  187. }
  188. catch (MissingFieldException)
  189. {
  190. // hit a readonly property
  191. break;
  192. }
  193. }
  194. }
  195. public static object Coerce(object value, Type toType)
  196. {
  197. if (value == null) return null;
  198. var args = new object[] {toType};
  199. var dispatcher = GetDispatcher(value, "$Coerce$", new[] {toType}, () => CreateCoerceDispatcher(value, toType));
  200. return dispatcher(value, args);
  201. }
  202. private static Dispatcher CreateCoerceDispatcher(object value, Type toType)
  203. {
  204. if (toType.IsInstanceOfType(value)) return IdentityDispatcher;
  205. if (value is ICoercible) return CoercibleDispatcher;
  206. var fromType = value.GetType();
  207. if (IsPromotableNumeric(fromType) && IsPromotableNumeric(toType))
  208. return EmitPromotionDispatcher(fromType, toType);
  209. var method = FindImplicitConversionOperator(fromType, toType);
  210. if (null == method) return IdentityDispatcher;
  211. return EmitImplicitConversionDispatcher(method);
  212. }
  213. private static Dispatcher EmitPromotionDispatcher(Type fromType, Type toType)
  214. {
  215. return (Dispatcher)Delegate.CreateDelegate(typeof(Dispatcher), typeof(NumericPromotions).GetMethod("From" + Type.GetTypeCode(fromType) + "To" + Type.GetTypeCode(toType)));
  216. }
  217. private static bool IsPromotableNumeric(Type fromType)
  218. {
  219. return IsPromotableNumeric(Type.GetTypeCode(fromType));
  220. }
  221. private static Dispatcher EmitImplicitConversionDispatcher(MethodInfo method)
  222. {
  223. #if NO_SYSTEM_REFLECTION_EMIT
  224. return (target, args) => method.Invoke(null, new object[] { target });
  225. #else
  226. return new DynamicDispatching.Emitters.ImplicitConversionEmitter(method).Emit();
  227. #endif
  228. }
  229. private static object CoercibleDispatcher(object o, object[] args)
  230. {
  231. return ((ICoercible) o).Coerce((Type)args[0]);
  232. }
  233. private static object IdentityDispatcher(object o, object[] args)
  234. {
  235. return o;
  236. }
  237. public static object GetSlice(object target, string name, object[] args)
  238. {
  239. var dispatcher = GetDispatcher(target, args, name + "[]", () => CreateGetSliceDispatcher(target, name, args));
  240. return dispatcher(target, args);
  241. }
  242. private static Dispatcher CreateGetSliceDispatcher(object target, string name, object[] args)
  243. {
  244. var duck = target as IQuackFu;
  245. if (null != duck)
  246. return (o, arguments) => ((IQuackFu) o).QuackGet(name, arguments);
  247. if ("" == name
  248. && args.Length == 1
  249. && target is Array) return GetArraySlice;
  250. return new SliceDispatcherFactory(_extensions, target, target.GetType(), name, args).CreateGetter();
  251. }
  252. private static object GetArraySlice(object target, object[] args)
  253. {
  254. var list = (IList)target;
  255. return list[NormalizeIndex(list.Count, (int)args[0])];
  256. }
  257. public static object SetSlice(object target, string name, object[] args)
  258. {
  259. var dispatcher = GetDispatcher(target, args, name + "[]=", () => CreateSetSliceDispatcher(target, name, args));
  260. return dispatcher(target, args);
  261. }
  262. static Dispatcher CreateSetSliceDispatcher(object target, string name, object[] args)
  263. {
  264. var duck = target as IQuackFu;
  265. if (null != duck)
  266. {
  267. return
  268. (o, arguments) =>
  269. ((IQuackFu) o).QuackSet(name, (object[]) GetRange2(arguments, 0, arguments.Length - 1), arguments[arguments.Length - 1]);
  270. }
  271. if ("" == name
  272. && 2 == args.Length
  273. && target is Array) return SetArraySlice;
  274. return new SliceDispatcherFactory(_extensions, target, target.GetType(), name, args).CreateSetter();
  275. }
  276. private static object SetArraySlice(object target, object[] args)
  277. {
  278. var list = (IList)target;
  279. list[NormalizeIndex(list.Count, (int)args[0])] = args[1];
  280. return args[1];
  281. }
  282. internal static String GetDefaultMemberName(Type type)
  283. {
  284. var attribute = (DefaultMemberAttribute)Attribute.GetCustomAttribute(type, typeof(DefaultMemberAttribute));
  285. return attribute != null ? attribute.MemberName : "";
  286. }
  287. public static object InvokeCallable(object target, object[] args)
  288. {
  289. if (null == target) throw new ArgumentNullException("target");
  290. if (null == args) throw new ArgumentNullException("args");
  291. var c = target as ICallable;
  292. if (null != c) return c.Call(args);
  293. var d = target as Delegate;
  294. if (null != d) return d.DynamicInvoke(args);
  295. var type = target as Type;
  296. if (null != type) return Activator.CreateInstance(type, args);
  297. return ((MethodInfo)target).Invoke(null, args);
  298. }
  299. private static bool IsNumeric(TypeCode code)
  300. {
  301. switch (code)
  302. {
  303. case TypeCode.Byte: return true;
  304. case TypeCode.SByte: return true;
  305. case TypeCode.Int16: return true;
  306. case TypeCode.Int32: return true;
  307. case TypeCode.Int64: return true;
  308. case TypeCode.UInt16: return true;
  309. case TypeCode.UInt32: return true;
  310. case TypeCode.UInt64: return true;
  311. case TypeCode.Single: return true;
  312. case TypeCode.Double: return true;
  313. case TypeCode.Decimal: return true;
  314. }
  315. return false;
  316. }
  317. public static object InvokeBinaryOperator(string operatorName, object lhs, object rhs)
  318. {
  319. Type lhsType = lhs.GetType();
  320. Type rhsType = rhs.GetType();
  321. TypeCode lhsTypeCode = Type.GetTypeCode(lhsType);
  322. TypeCode rhsTypeCode = Type.GetTypeCode(rhsType);
  323. if (IsNumeric(lhsTypeCode) && IsNumeric(rhsTypeCode))
  324. {
  325. // HACK: optimization to get to the correct operators faster
  326. // is it worthy?
  327. switch (((int)operatorName[3] << 8) + (int)operatorName[operatorName.Length - 1])
  328. {
  329. case ((int)'A' << 8) + (int)'n': // op_Addition
  330. return op_Addition(lhs, lhsTypeCode, rhs, rhsTypeCode);
  331. case ((int)'S' << 8) + (int)'n': // op_Subtraction
  332. return op_Subtraction(lhs, lhsTypeCode, rhs, rhsTypeCode);
  333. case ((int)'M' << 8) + (int)'y': // op_Multiply
  334. return op_Multiply(lhs, lhsTypeCode, rhs, rhsTypeCode);
  335. case ((int)'D' << 8) + (int)'n': // op_Division
  336. return op_Division(lhs, lhsTypeCode, rhs, rhsTypeCode);
  337. case ((int)'M' << 8) + (int)'s': // op_Modulus
  338. return op_Modulus(lhs, lhsTypeCode, rhs, rhsTypeCode);
  339. case ((int)'E' << 8) + (int)'n': // op_Exponentiation
  340. return op_Exponentiation(lhs, lhsTypeCode, rhs, rhsTypeCode);
  341. case ((int)'L' << 8) + (int)'n': // op_LessThan
  342. return op_LessThan(lhs, lhsTypeCode, rhs, rhsTypeCode);
  343. case ((int)'L' << 8) + (int)'l': // op_LessThanOrEqual
  344. return op_LessThanOrEqual(lhs, lhsTypeCode, rhs, rhsTypeCode);
  345. case ((int)'G' << 8) + (int)'n': // op_GreaterThan
  346. return op_GreaterThan(lhs, lhsTypeCode, rhs, rhsTypeCode);
  347. case ((int)'G' << 8) + (int)'l': // op_GreaterThanOrEqual
  348. return op_GreaterThanOrEqual(lhs, lhsTypeCode, rhs, rhsTypeCode);
  349. case ((int)'B' << 8) + (int)'r': // op_BitwiseOr
  350. return op_BitwiseOr(lhs, lhsTypeCode, rhs, rhsTypeCode);
  351. case ((int)'B' << 8) + (int)'d': // op_BitwiseAnd
  352. return op_BitwiseAnd(lhs, lhsTypeCode, rhs, rhsTypeCode);
  353. case ((int)'E' << 8) + (int)'r': // op_ExclusiveOr
  354. return op_ExclusiveOr(lhs, lhsTypeCode, rhs, rhsTypeCode);
  355. case ((int)'S' << 8) + (int)'t': // op_ShiftLeft/Right
  356. return operatorName[8] == 'L' ?
  357. op_ShiftLeft(lhs, lhsTypeCode, rhs, rhsTypeCode) :
  358. op_ShiftRight(lhs, lhsTypeCode, rhs, rhsTypeCode);
  359. case ((int)'M' << 8) + (int)'h': // op_Match
  360. case ((int)'N' << 8) + (int)'h': // op_NotMatch
  361. case ((int)'M' << 8) + (int)'r': // op_Member
  362. case ((int)'N' << 8) + (int)'r': // op_NotMember
  363. default:
  364. throw new MissingMethodException(MissingOperatorMessageFor(operatorName, lhsType, rhsType));
  365. }
  366. }
  367. else
  368. {
  369. var args = new object[] { lhs, rhs };
  370. var duck = lhs as IQuackFu;
  371. if (null != duck)
  372. return duck.QuackInvoke(operatorName, args);
  373. duck = rhs as IQuackFu;
  374. if (null != duck)
  375. return duck.QuackInvoke(operatorName, args);
  376. try
  377. {
  378. // TODO: first resolve the right method on either
  379. // lhs and rhs
  380. // and then cache the final information
  381. return Invoke(lhsType, operatorName, args);
  382. }
  383. catch (MissingMethodException x)
  384. {
  385. try
  386. {
  387. return Invoke(rhsType, operatorName, args);
  388. }
  389. catch (MissingMethodException)
  390. {
  391. try
  392. {
  393. return InvokeRuntimeServicesOperator(operatorName, args);
  394. }
  395. catch (MissingMethodException)
  396. {
  397. }
  398. }
  399. throw new MissingMethodException(MissingOperatorMessageFor(operatorName, lhsType, rhsType), x); // always throw the original exception
  400. }
  401. }
  402. }
  403. private static string MissingOperatorMessageFor(string operatorName, Type lhsType, Type rhsType)
  404. {
  405. return string.Format("{0} is not applicable to operands '{1}' and '{2}'.", FormatOperatorName(operatorName), lhsType, rhsType);
  406. }
  407. private static string FormatOperatorName(string operatorName)
  408. {
  409. Debug.Assert(operatorName.StartsWith("op_"));
  410. var result = new StringBuilder(operatorName.Length);
  411. result.Append(operatorName[3]);
  412. foreach (var ch in operatorName.Substring(4))
  413. if (char.IsUpper(ch))
  414. {
  415. result.Append(" ");
  416. result.Append(char.ToLower(ch));
  417. }
  418. else
  419. result.Append(ch);
  420. return result.ToString();
  421. }
  422. public static object InvokeUnaryOperator(string operatorName, object operand)
  423. {
  424. Type operandType = operand.GetType();
  425. TypeCode operandTypeCode = Type.GetTypeCode(operandType);
  426. if (IsNumeric(operandTypeCode))
  427. {
  428. // HACK: optimization to get to the correct operators faster
  429. // is it worthy?
  430. switch (((int)operatorName[3] << 8) + (int)operatorName[operatorName.Length - 1])
  431. {
  432. case ((int)'U' << 8) + (int)'n': // op_UnaryNegation
  433. return op_UnaryNegation(operand, operandTypeCode);
  434. default:
  435. throw new ArgumentException(operatorName + " " + operand);
  436. }
  437. }
  438. else
  439. {
  440. var args = new[] { operand };
  441. var duck = operand as IQuackFu;
  442. if (duck != null)
  443. return duck.QuackInvoke(operatorName, args);
  444. try
  445. {
  446. return Invoke(operandType, operatorName, args);
  447. }
  448. catch (MissingMethodException)
  449. {
  450. try
  451. {
  452. return InvokeRuntimeServicesOperator(operatorName, args);
  453. }
  454. catch (MissingMethodException)
  455. {
  456. }
  457. throw; // always throw the original exception
  458. }
  459. }
  460. }
  461. private static object InvokeRuntimeServicesOperator(string operatorName, object[] args)
  462. {
  463. return Invoke(RuntimeServicesType, operatorName, args);
  464. }
  465. public static object MoveNext(IEnumerator enumerator)
  466. {
  467. if (enumerator == null)
  468. throw new ApplicationException(StringResources.CantUnpackNull);
  469. if (!enumerator.MoveNext())
  470. throw new ApplicationException(StringResources.UnpackListOfWrongSize);
  471. return enumerator.Current;
  472. }
  473. public static int Len(object obj)
  474. {
  475. if (obj != null)
  476. {
  477. var collection = obj as ICollection;
  478. if (collection != null) return collection.Count;
  479. var s = obj as string;
  480. if (s != null) return s.Length;
  481. }
  482. throw new ArgumentException();
  483. }
  484. public static string Mid(string s, int begin, int end)
  485. {
  486. begin = NormalizeStringIndex(s, begin);
  487. end = NormalizeStringIndex(s, end);
  488. return s.Substring(begin, end - begin);
  489. }
  490. public static Array GetRange1(Array source, int begin)
  491. {
  492. return GetRange2(source, begin, source.Length);
  493. }
  494. public static Array GetRange2(Array source, int begin, int end)
  495. {
  496. int sourceLen = source.Length;
  497. begin = NormalizeIndex(sourceLen, begin);
  498. end = NormalizeIndex(sourceLen, end);
  499. int targetLen = Math.Max(0, end - begin);
  500. Array target = Array.CreateInstance(source.GetType().GetElementType(), targetLen);
  501. Array.Copy(source, begin, target, 0, targetLen);
  502. return target;
  503. }
  504. public static void SetMultiDimensionalRange1(Array source, Array dest, int[] ranges, bool[] compute_end, bool[] collapse)
  505. {
  506. if (dest.Rank != ranges.Length/2)
  507. throw new Exception("invalid range passed: " + ranges.Length/2 + ", expected " + dest.Rank*2);
  508. for (var i = 0; i < dest.Rank; i++)
  509. {
  510. if (compute_end[i])
  511. ranges[2 * i + 1] = dest.GetLength(i);
  512. if (ranges[2 * i] < 0 ||
  513. ranges[2 * i] >= dest.GetLength(i) ||
  514. ranges[2 * i + 1] > dest.GetLength(i) ||
  515. ranges[2 * i + 1] <= ranges[2 * i])
  516. {
  517. // FIXME: Better error reporting
  518. throw new ApplicationException("Invalid array.");
  519. }
  520. }
  521. var destSubsetRank = 0;
  522. foreach (var val in collapse)
  523. {
  524. if (!val)
  525. destSubsetRank++;
  526. }
  527. if (destSubsetRank == 0)
  528. destSubsetRank = 1;
  529. if (source.Rank != destSubsetRank)
  530. {
  531. throw new ApplicationException(String.Format("Cannot assign array of rank {0} into an array subset of rank {1}.",source.Rank,destSubsetRank));
  532. }
  533. int[] lensDest = new int[dest.Rank];
  534. int[] lensDestSubset = new int[destSubsetRank];
  535. int[] lensSrc = new int[source.Rank];
  536. int rankIndex = 0;
  537. bool length_mismatch = false;
  538. for (int i = 0; i < dest.Rank; i++)
  539. {
  540. lensDest[i] = ranges[2 * i + 1] - ranges[2 * i];
  541. if (!collapse[i])
  542. {
  543. lensDestSubset[rankIndex] = lensDest[i];
  544. lensSrc[rankIndex] = source.GetLength(rankIndex);
  545. if (lensSrc[rankIndex] != lensDest[i])
  546. {
  547. length_mismatch = true;
  548. }
  549. rankIndex++;
  550. }
  551. }
  552. if (length_mismatch)
  553. {
  554. StringBuilder source_dims = new StringBuilder(lensSrc[0]);
  555. StringBuilder dest_subset_dims = new StringBuilder(lensDestSubset[0]);
  556. for (int i = 1; i < source.Rank; i++)
  557. {
  558. source_dims.Append(" x ");
  559. source_dims.Append(lensSrc[i]);
  560. dest_subset_dims.Append(" x ");
  561. dest_subset_dims.Append(lensDestSubset[i]);
  562. }
  563. throw new ApplicationException(String.Format("Cannot assign array with dimensions {0} into array subset of dimensions {1}.",source_dims.ToString(),dest_subset_dims.ToString()));
  564. }
  565. int[] prodInd = new int[source.Rank];
  566. prodInd[0] = lensSrc[0];
  567. for (int i = 1; i < source.Rank; i++)
  568. prodInd[i] = prodInd[i - 1]*lensSrc[i];
  569. int[] indexDest = new int[dest.Rank];
  570. int[] indexSrc = new int[source.Rank];
  571. for (int i = 0; i < source.Length; i++)
  572. {
  573. int counter = 0;
  574. for (int j = 0; j < dest.Rank; j++)
  575. {
  576. if (collapse[j])
  577. indexDest[j] = ranges[2*j];
  578. else
  579. {
  580. indexSrc[counter] = i%prodInd[counter];
  581. indexDest[j] = indexSrc[counter] + ranges[2*j];
  582. counter++;
  583. }
  584. }
  585. dest.SetValue(source.GetValue(indexSrc), indexDest);
  586. }
  587. }
  588. public static Array GetMultiDimensionalRange1(Array source, int[] ranges, bool[] compute_end, bool[] collapse)
  589. {
  590. int rankSrc = source.Rank;
  591. int[] lensSrc = new int[rankSrc];
  592. int collapseSize = 0;
  593. for (int i = 0; i < rankSrc; i++)
  594. {
  595. ranges[2 * i] = NormalizeIndex(source.GetLength(i), ranges[2 * i]);
  596. if (compute_end[i])
  597. ranges[2*i + 1] = source.GetLength(i);
  598. else
  599. ranges[2 * i + 1] = NormalizeIndex(source.GetLength(i), ranges[2 * i + 1]);
  600. lensSrc[i] = ranges[2 * i + 1] - ranges[2 * i];
  601. collapseSize += collapse[i] ? 1 : 0;
  602. }
  603. int rankDest = rankSrc - collapseSize;
  604. int[] lensDest = new int[rankDest];
  605. int rankIndex = 0;
  606. for (int i = 0; i < rankSrc; i++)
  607. {
  608. if (!collapse[i])
  609. {
  610. lensDest[rankIndex] = lensSrc[i];
  611. rankIndex++;
  612. }
  613. }
  614. if (rankDest == 0)
  615. {
  616. rankDest = 1;
  617. lensDest = new int[1];
  618. lensDest[0] = 1;
  619. }
  620. Array dest = Array.CreateInstance(source.GetType().GetElementType(), lensDest);
  621. int[] modInd = new int[rankSrc];
  622. int[] indicesDest = new int[rankDest];
  623. int[] indicesSrc = new int[rankSrc];
  624. for (int i = 0; i < rankSrc; i++)
  625. {
  626. if (i == 0)
  627. modInd[i] = dest.Length;
  628. else
  629. modInd[i] = modInd[i - 1]/lensSrc[i - 1];
  630. }
  631. for (int i = 0; i < dest.Length; i++)
  632. {
  633. int destIndex = 0;
  634. for (int j = 0; j < rankSrc; j++)
  635. {
  636. int index = (i % modInd[j]) / (modInd[j] / lensSrc[j]);
  637. indicesSrc[j] = ranges[2 * j] + index;
  638. if (!collapse[j])
  639. {
  640. indicesDest[destIndex] = indicesSrc[j] - ranges[2 * j];
  641. destIndex++;
  642. }
  643. }
  644. dest.SetValue(source.GetValue(indicesSrc), indicesDest);
  645. }
  646. return dest;
  647. }
  648. public static void CheckArrayUnpack(Array array, int expected)
  649. {
  650. if (null == array)
  651. {
  652. throw new ApplicationException(StringResources.CantUnpackNull);
  653. }
  654. if (expected > array.Length)
  655. {
  656. Error(StringResources.UnpackArrayOfWrongSize, expected, array.Length);
  657. }
  658. }
  659. /*
  660. * Since index normalization is quite performance-sensitive, the
  661. * method body is duplicated on Normalize* methods to increase
  662. * likelihood that the JIT will inline the call in the caller.
  663. * On Mono it gives ~30% improvement since it triggers inlining On.
  664. */
  665. public static int NormalizeIndex(int len, int index)
  666. {
  667. return index < 0 ? Math.Max(0, index + len) : Math.Min(index, len);
  668. }
  669. public static int NormalizeArrayIndex(Array array, int index)
  670. {
  671. return index < 0 ? Math.Max(0, index + array.Length) : Math.Min(index, array.Length);
  672. }
  673. public static int NormalizeStringIndex(string s, int index)
  674. {
  675. return index < 0 ? Math.Max(0, index + s.Length) : Math.Min(index, s.Length);
  676. }
  677. public static IEnumerable GetEnumerable(object enumerable)
  678. {
  679. if (null == enumerable)
  680. throw new ApplicationException(StringResources.CantEnumerateNull);
  681. var iterator = enumerable as IEnumerable;
  682. if (null != iterator) return iterator;
  683. var reader = enumerable as TextReader;
  684. if (null != reader) return TextReaderEnumerator.lines(reader);
  685. throw new ApplicationException(StringResources.ArgumentNotEnumerable);
  686. }
  687. #region global operators
  688. public static Array AddArrays(Type resultingElementType, Array lhs, Array rhs)
  689. {
  690. int resultingLen = lhs.Length + rhs.Length;
  691. Array result = Array.CreateInstance(resultingElementType, resultingLen);
  692. Array.Copy(lhs, 0, result, 0, lhs.Length);
  693. Array.Copy(rhs, 0, result, lhs.Length, rhs.Length);
  694. return result;
  695. }
  696. public static string op_Addition(string lhs, string rhs)
  697. {
  698. return string.Concat(lhs, rhs);
  699. }
  700. public static string op_Addition(string lhs, object rhs)
  701. {
  702. return string.Concat(lhs, rhs);
  703. }
  704. public static string op_Addition(object lhs, string rhs)
  705. {
  706. return string.Concat(lhs, rhs);
  707. }
  708. public static Array op_Multiply(Array lhs, int count)
  709. {
  710. if (count < 0)
  711. {
  712. throw new ArgumentOutOfRangeException("count");
  713. }
  714. Type type = lhs.GetType();
  715. if (1 != type.GetArrayRank())
  716. {
  717. throw new ArgumentException("lhs");
  718. }
  719. int length = lhs.Length;
  720. Array result = Array.CreateInstance(type.GetElementType(), length * count);
  721. int destinationIndex = 0;
  722. for (int i = 0; i < count; ++i)
  723. {
  724. Array.Copy(lhs, 0, result, destinationIndex, length);
  725. destinationIndex += length;
  726. }
  727. return result;
  728. }
  729. public static Array op_Multiply(int count, Array rhs)
  730. {
  731. return op_Multiply(rhs, count);
  732. }
  733. public static string op_Multiply(string lhs, int count)
  734. {
  735. if (count < 0)
  736. {
  737. throw new ArgumentOutOfRangeException("count");
  738. }
  739. string result = null;
  740. if (null != lhs)
  741. {
  742. StringBuilder builder = new StringBuilder(lhs.Length * count);
  743. for (int i = 0; i < count; ++i)
  744. {
  745. builder.Append(lhs);
  746. }
  747. result = builder.ToString();
  748. }
  749. return result;
  750. }
  751. public static string op_Multiply(int count, string rhs)
  752. {
  753. return op_Multiply(rhs, count);
  754. }
  755. public static bool op_NotMember(string lhs, string rhs)
  756. {
  757. return !op_Member(lhs, rhs);
  758. }
  759. public static bool op_Member(string lhs, string rhs)
  760. {
  761. if (null == lhs || null == rhs)
  762. return false;
  763. return rhs.IndexOf(lhs) > -1;
  764. }
  765. public static bool op_Member(char lhs, string rhs)
  766. {
  767. if (rhs == null) return false;
  768. return rhs.IndexOf(lhs) > -1;
  769. }
  770. #if !NO_REGEX
  771. public static bool op_Match(string input, System.Text.RegularExpressions.Regex pattern)
  772. {
  773. return pattern.IsMatch(input);
  774. }
  775. public static bool op_Match(string input, string pattern)
  776. {
  777. return System.Text.RegularExpressions.Regex.IsMatch(input, pattern);
  778. }
  779. public static bool op_NotMatch(string input, System.Text.RegularExpressions.Regex pattern)
  780. {
  781. return !op_Match(input, pattern);
  782. }
  783. public static bool op_NotMatch(string input, string pattern)
  784. {
  785. return !op_Match(input, pattern);
  786. }
  787. #endif
  788. public static string op_Modulus(string lhs, IEnumerable rhs)
  789. {
  790. return string.Format(lhs, Builtins.array(rhs));
  791. }
  792. public static string op_Modulus(string lhs, object[] rhs)
  793. {
  794. return string.Format(lhs, rhs);
  795. }
  796. public static bool op_Member(object lhs, IList rhs)
  797. {
  798. if (null == rhs)
  799. {
  800. return false;
  801. }
  802. return rhs.Contains(lhs);
  803. }
  804. public static bool op_NotMember(object lhs, IList rhs)
  805. {
  806. return !op_Member(lhs, rhs);
  807. }
  808. public static bool op_Member(object lhs, IDictionary rhs)
  809. {
  810. if (null == rhs)
  811. {
  812. return false;
  813. }
  814. return rhs.Contains(lhs);
  815. }
  816. public static bool op_NotMember(object lhs, IDictionary rhs)
  817. {
  818. return !op_Member(lhs, rhs);
  819. }
  820. public static bool op_Member(object lhs, IEnumerable rhs)
  821. {
  822. if (null == rhs)
  823. {
  824. return false;
  825. }
  826. foreach (object item in rhs)
  827. {
  828. if (EqualityOperator(lhs, item))
  829. {
  830. return true;
  831. }
  832. }
  833. return false;
  834. }
  835. public static bool op_NotMember(object lhs, IEnumerable rhs)
  836. {
  837. return !op_Member(lhs, rhs);
  838. }
  839. public static bool EqualityOperator(object lhs, object rhs)
  840. {
  841. if (lhs == rhs) return true;
  842. // Some types do overload Equals to compare
  843. // against null values
  844. if (null == lhs) return rhs.Equals(lhs);
  845. if (null == rhs) return lhs.Equals(rhs);
  846. TypeCode lhsTypeCode = Type.GetTypeCode(lhs.GetType());
  847. TypeCode rhsTypeCode = Type.GetTypeCode(rhs.GetType());
  848. if (IsNumeric(lhsTypeCode) && IsNumeric(rhsTypeCode))
  849. {
  850. return EqualityOperator(lhs, lhsTypeCode, rhs, rhsTypeCode);
  851. }
  852. Array lhsa = lhs as Array;
  853. if (null != lhsa)
  854. {
  855. Array rhsa = rhs as Array;
  856. if (null != rhsa)
  857. {
  858. return ArrayEqualityImpl(lhsa, rhsa);
  859. }
  860. }
  861. return lhs.Equals(rhs) || rhs.Equals(lhs);
  862. }
  863. public static bool op_Equality(Array lhs, Array rhs)
  864. {
  865. if (lhs == rhs)
  866. {
  867. return true;
  868. }
  869. if (null == lhs || null == rhs)
  870. {
  871. return false;
  872. }
  873. return ArrayEqualityImpl(lhs, rhs);
  874. }
  875. static bool ArrayEqualityImpl(Array lhs, Array rhs)
  876. {
  877. if (1 != lhs.Rank || 1 != rhs.Rank)
  878. {
  879. throw new ArgumentException("array rank must be 1");
  880. }
  881. if (lhs.Length != rhs.Length)
  882. {
  883. return false;
  884. }
  885. for (int i = 0; i < lhs.Length; ++i)
  886. {
  887. if (!EqualityOperator(lhs.GetValue(i), rhs.GetValue(i)))
  888. {
  889. return false;
  890. }
  891. }
  892. return true;
  893. }
  894. #endregion
  895. #region dynamic operator for primitive types
  896. private static TypeCode GetConvertTypeCode(TypeCode lhsTypeCode, TypeCode rhsTypeCode)
  897. {
  898. /* C# ECMA Spec V2
  899. * 14.2.6.2 Binary numeric promotions
  900. * This clause is informative.
  901. * Binary numeric promotion occurs for the operands of the predefined +, ?, *, /, %, &, |, ^, ==, !=, >, <, >=,
  902. * and <= binary operators. Binary numeric promotion implicitly converts both operands to a common type
  903. * which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric
  904. * promotion consists of applying the following rules, in the order they appear here:
  905. * � If either operand is of type decimal, the other operand is converted to type decimal, or a compiletime
  906. * error occurs if the other operand is of type float or double.
  907. * � Otherwise, if either operand is of type double, the other operand is converted to type double.
  908. * � Otherwise, if either operand is of type float, the other operand is converted to type float.
  909. * � Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a
  910. * compile-time error occurs if the other operand is of type sbyte, short, int, or long.
  911. * � Otherwise, if either operand is of type long, the other operand is converted to type long.
  912. * � Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int,
  913. * both operands are converted to type long.
  914. * � Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  915. * � Otherwise, both operands are converted to type int.
  916. * [Note: The first rule disallows any operations that mix the decimal type with the double and float types.
  917. * The rule follows from the fact that there are no implicit conversions between the decimal type and the
  918. * double and float types. end note]
  919. * [Note: Also note that it is not possible for an operand to be of type ulong when the other operand is of a
  920. * signed integral type. The reason is that no integral type exists that can represent the full range of ulong as
  921. * well as the signed integral types. end note]
  922. * In both of the above cases, a cast expression can be used to explicitly convert one operand to a type that is
  923. * compatible with the other operand.
  924. */
  925. if (TypeCode.Decimal == lhsTypeCode || TypeCode.Decimal == rhsTypeCode)
  926. {
  927. return TypeCode.Decimal; // not per ECMA spec
  928. }
  929. if (TypeCode.Double == lhsTypeCode || TypeCode.Double == rhsTypeCode)
  930. {
  931. return TypeCode.Double;
  932. }
  933. if (TypeCode.Single == lhsTypeCode || TypeCode.Single == rhsTypeCode)
  934. {
  935. return TypeCode.Single;
  936. }
  937. if (TypeCode.UInt64 == lhsTypeCode)
  938. {
  939. if (TypeCode.SByte == rhsTypeCode || TypeCode.Int16 == rhsTypeCode ||
  940. TypeCode.Int32 == rhsTypeCode || TypeCode.Int64 == rhsTypeCode)
  941. {
  942. // throw new ArgumentException("ulong <op> " + rhsTypeCode);
  943. return TypeCode.Int64; // not per Ecma spec
  944. }
  945. return TypeCode.UInt64;
  946. }
  947. if (TypeCode.UInt64 == rhsTypeCode)
  948. {
  949. if (TypeCode.SByte == lhsTypeCode || TypeCode.Int16 == lhsTypeCode ||
  950. TypeCode.Int32 == lhsTypeCode || TypeCode.Int64 == lhsTypeCode)
  951. {
  952. // throw new ArgumentException(lhsTypeCode + " <op> ulong");
  953. return TypeCode.Int64; // not per Ecma spec
  954. }
  955. return TypeCode.UInt64;
  956. }
  957. if (TypeCode.Int64 == lhsTypeCode || TypeCode.Int64 == rhsTypeCode)
  958. {
  959. return TypeCode.Int64;
  960. }
  961. if (TypeCode.UInt32 == lhsTypeCode)
  962. {
  963. if (TypeCode.SByte == rhsTypeCode || TypeCode.Int16 == rhsTypeCode ||
  964. TypeCode.Int32 == rhsTypeCode)
  965. {
  966. return TypeCode.Int64;
  967. }
  968. return TypeCode.UInt32;
  969. }
  970. if (TypeCode.UInt32 == rhsTypeCode)
  971. {
  972. if (TypeCode.SByte == lhsTypeCode || TypeCode.Int16 == lhsTypeCode ||
  973. TypeCode.Int32 == lhsTypeCode)
  974. {
  975. return TypeCode.Int64;
  976. }
  977. return TypeCode.UInt32;
  978. }
  979. return TypeCode.Int32;
  980. }
  981. private static object op_Multiply(object lhs, TypeCode lhsTypeCode,
  982. object rhs, TypeCode rhsTypeCode)
  983. {
  984. IConvertible lhsConvertible = (IConvertible)lhs;
  985. IConvertible rhsConvertible = (IConvertible)rhs;
  986. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  987. {
  988. case TypeCode.Decimal:
  989. return lhsConvertible.ToDecimal(null) * rhsConvertible.ToDecimal(null);
  990. case TypeCode.Double:
  991. return lhsConvertible.ToDouble(null) * rhsConvertible.ToDouble(null);
  992. case TypeCode.Single:
  993. return lhsConvertible.ToSingle(null) * rhsConvertible.ToSingle(null);
  994. case TypeCode.UInt64:
  995. return lhsConvertible.ToUInt64(null) * rhsConvertible.ToUInt64(null);
  996. case TypeCode.Int64:
  997. return lhsConvertible.ToInt64(null) * rhsConvertible.ToInt64(null);
  998. case TypeCode.UInt32:
  999. return lhsConvertible.ToUInt32(null) * rhsConvertible.ToUInt32(null);
  1000. default:
  1001. return lhsConvertible.ToInt32(null) * rhsConvertible.ToInt32(null);
  1002. }
  1003. }
  1004. private static object op_Division(object lhs, TypeCode lhsTypeCode,
  1005. object rhs, TypeCode rhsTypeCode)
  1006. {
  1007. IConvertible lhsConvertible = (IConvertible)lhs;
  1008. IConvertible rhsConvertible = (IConvertible)rhs;
  1009. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1010. {
  1011. case TypeCode.Decimal:
  1012. return lhsConvertible.ToDecimal(null) / rhsConvertible.ToDecimal(null);
  1013. case TypeCode.Double:
  1014. return lhsConvertible.ToDouble(null) / rhsConvertible.ToDouble(null);
  1015. case TypeCode.Single:
  1016. return lhsConvertible.ToSingle(null) / rhsConvertible.ToSingle(null);
  1017. case TypeCode.UInt64:
  1018. return lhsConvertible.ToUInt64(null) / rhsConvertible.ToUInt64(null);
  1019. case TypeCode.Int64:
  1020. return lhsConvertible.ToInt64(null) / rhsConvertible.ToInt64(null);
  1021. case TypeCode.UInt32:
  1022. return lhsConvertible.ToUInt32(null) / rhsConvertible.ToUInt32(null);
  1023. default:
  1024. return lhsConvertible.ToInt32(null) / rhsConvertible.ToInt32(null);
  1025. }
  1026. }
  1027. private static object op_Addition(object lhs, TypeCode lhsTypeCode,
  1028. object rhs, TypeCode rhsTypeCode)
  1029. {
  1030. IConvertible lhsConvertible = (IConvertible)lhs;
  1031. IConvertible rhsConvertible = (IConvertible)rhs;
  1032. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1033. {
  1034. case TypeCode.Decimal:
  1035. return lhsConvertible.ToDecimal(null) + rhsConvertible.ToDecimal(null);
  1036. case TypeCode.Double:
  1037. return lhsConvertible.ToDouble(null) + rhsConvertible.ToDouble(null);
  1038. case TypeCode.Single:
  1039. return lhsConvertible.ToSingle(null) + rhsConvertible.ToSingle(null);
  1040. case TypeCode.UInt64:
  1041. return lhsConvertible.ToUInt64(null) + rhsConvertible.ToUInt64(null);
  1042. case TypeCode.Int64:
  1043. return lhsConvertible.ToInt64(null) + rhsConvertible.ToInt64(null);
  1044. case TypeCode.UInt32:
  1045. return lhsConvertible.ToUInt32(null) + rhsConvertible.ToUInt32(null);
  1046. default:
  1047. return lhsConvertible.ToInt32(null) + rhsConvertible.ToInt32(null);
  1048. }
  1049. }
  1050. private static object op_Subtraction(object lhs, TypeCode lhsTypeCode,
  1051. object rhs, TypeCode rhsTypeCode)
  1052. {
  1053. IConvertible lhsConvertible = (IConvertible)lhs;
  1054. IConvertible rhsConvertible = (IConvertible)rhs;
  1055. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1056. {
  1057. case TypeCode.Decimal:
  1058. return lhsConvertible.ToDecimal(null) - rhsConvertible.ToDecimal(null);
  1059. case TypeCode.Double:
  1060. return lhsConvertible.ToDouble(null) - rhsConvertible.ToDouble(null);
  1061. case TypeCode.Single:
  1062. return lhsConvertible.ToSingle(null) - rhsConvertible.ToSingle(null);
  1063. case TypeCode.UInt64:
  1064. return lhsConvertible.ToUInt64(null) - rhsConvertible.ToUInt64(null);
  1065. case TypeCode.Int64:
  1066. return lhsConvertible.ToInt64(null) - rhsConvertible.ToInt64(null);
  1067. case TypeCode.UInt32:
  1068. return lhsConvertible.ToUInt32(null) - rhsConvertible.ToUInt32(null);
  1069. default:
  1070. return lhsConvertible.ToInt32(null) - rhsConvertible.ToInt32(null);
  1071. }
  1072. }
  1073. private static bool EqualityOperator(object lhs, TypeCode lhsTypeCode,
  1074. object rhs, TypeCode rhsTypeCode)
  1075. {
  1076. IConvertible lhsConvertible = (IConvertible)lhs;
  1077. IConvertible rhsConvertible = (IConvertible)rhs;
  1078. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1079. {
  1080. case TypeCode.Decimal:
  1081. return lhsConvertible.ToDecimal(null) == rhsConvertible.ToDecimal(null);
  1082. case TypeCode.Double:
  1083. return lhsConvertible.ToDouble(null) == rhsConvertible.ToDouble(null);
  1084. case TypeCode.Single:
  1085. return lhsConvertible.ToSingle(null) == rhsConvertible.ToSingle(null);
  1086. case TypeCode.UInt64:
  1087. return lhsConvertible.ToUInt64(null) == rhsConvertible.ToUInt64(null);
  1088. case TypeCode.Int64:
  1089. return lhsConvertible.ToInt64(null) == rhsConvertible.ToInt64(null);
  1090. case TypeCode.UInt32:
  1091. return lhsConvertible.ToUInt32(null) == rhsConvertible.ToUInt32(null);
  1092. default:
  1093. return lhsConvertible.ToInt32(null) == rhsConvertible.ToInt32(null);
  1094. }
  1095. }
  1096. private static bool op_GreaterThan(object lhs, TypeCode lhsTypeCode,
  1097. object rhs, TypeCode rhsTypeCode)
  1098. {
  1099. IConvertible lhsConvertible = (IConvertible)lhs;
  1100. IConvertible rhsConvertible = (IConvertible)rhs;
  1101. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1102. {
  1103. case TypeCode.Decimal:
  1104. return lhsConvertible.ToDecimal(null) > rhsConvertible.ToDecimal(null);
  1105. case TypeCode.Double:
  1106. return lhsConvertible.ToDouble(null) > rhsConvertible.ToDouble(null);
  1107. case TypeCode.Single:
  1108. return lhsConvertible.ToSingle(null) > rhsConvertible.ToSingle(null);
  1109. case TypeCode.UInt64:
  1110. return lhsConvertible.ToUInt64(null) > rhsConvertible.ToUInt64(null);
  1111. case TypeCode.Int64:
  1112. return lhsConvertible.ToInt64(null) > rhsConvertible.ToInt64(null);
  1113. case TypeCode.UInt32:
  1114. return lhsConvertible.ToUInt32(null) > rhsConvertible.ToUInt32(null);
  1115. default:
  1116. return lhsConvertible.ToInt32(null) > rhsConvertible.ToInt32(null);
  1117. }
  1118. }
  1119. private static bool op_GreaterThanOrEqual(object lhs, TypeCode lhsTypeCode,
  1120. object rhs, TypeCode rhsTypeCode)
  1121. {
  1122. IConvertible lhsConvertible = (IConvertible)lhs;
  1123. IConvertible rhsConvertible = (IConvertible)rhs;
  1124. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1125. {
  1126. case TypeCode.Decimal:
  1127. return lhsConvertible.ToDecimal(null) >= rhsConvertible.ToDecimal(null);
  1128. case TypeCode.Double:
  1129. return lhsConvertible.ToDouble(null) >= rhsConvertible.ToDouble(null);
  1130. case TypeCode.Single:
  1131. return lhsConvertible.ToSingle(null) >= rhsConvertible.ToSingle(null);
  1132. case TypeCode.UInt64:
  1133. return lhsConvertible.ToUInt64(null) >= rhsConvertible.ToUInt64(null);
  1134. case TypeCode.Int64:
  1135. return lhsConvertible.ToInt64(null) >= rhsConvertible.ToInt64(null);
  1136. case TypeCode.UInt32:
  1137. return lhsConvertible.ToUInt32(null) >= rhsConvertible.ToUInt32(null);
  1138. default:
  1139. return lhsConvertible.ToInt32(null) >= rhsConvertible.ToInt32(null);
  1140. }
  1141. }
  1142. private static bool op_LessThan(object lhs, TypeCode lhsTypeCode,
  1143. object rhs, TypeCode rhsTypeCode)
  1144. {
  1145. IConvertible lhsConvertible = (IConvertible)lhs;
  1146. IConvertible rhsConvertible = (IConvertible)rhs;
  1147. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1148. {
  1149. case TypeCode.Decimal:
  1150. return lhsConvertible.ToDecimal(null) < rhsConvertible.ToDecimal(null);
  1151. case TypeCode.Double:
  1152. return lhsConvertible.ToDouble(null) < rhsConvertible.ToDouble(null);
  1153. case TypeCode.Single:
  1154. return lhsConvertible.ToSingle(null) < rhsConvertible.ToSingle(null);
  1155. case TypeCode.UInt64:
  1156. return lhsConvertible.ToUInt64(null) < rhsConvertible.ToUInt64(null);
  1157. case TypeCode.Int64:
  1158. return lhsConvertible.ToInt64(null) < rhsConvertible.ToInt64(null);
  1159. case TypeCode.UInt32:
  1160. return lhsConvertible.ToUInt32(null) < rhsConvertible.ToUInt32(null);
  1161. default:
  1162. return lhsConvertible.ToInt32(null) < rhsConvertible.ToInt32(null);
  1163. }
  1164. }
  1165. private static bool op_LessThanOrEqual(object lhs, TypeCode lhsTypeCode,
  1166. object rhs, TypeCode rhsTypeCode)
  1167. {
  1168. IConvertible lhsConvertible = (IConvertible)lhs;
  1169. IConvertible rhsConvertible = (IConvertible)rhs;
  1170. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1171. {
  1172. case TypeCode.Decimal:
  1173. return lhsConvertible.ToDecimal(null) <= rhsConvertible.ToDecimal(null);
  1174. case TypeCode.Double:
  1175. return lhsConvertible.ToDouble(null) <= rhsConvertible.ToDouble(null);
  1176. case TypeCode.Single:
  1177. return lhsConvertible.ToSingle(null) <= rhsConvertible.ToSingle(null);
  1178. case TypeCode.UInt64:
  1179. return lhsConvertible.ToUInt64(null) <= rhsConvertible.ToUInt64(null);
  1180. case TypeCode.Int64:
  1181. return lhsConvertible.ToInt64(null) <= rhsConvertible.ToInt64(null);
  1182. case TypeCode.UInt32:
  1183. return lhsConvertible.ToUInt32(null) <= rhsConvertible.ToUInt32(null);
  1184. default:
  1185. return lhsConvertible.ToInt32(null) <= rhsConvertible.ToInt32(null);
  1186. }
  1187. }
  1188. private static object op_Modulus(object lhs, TypeCode lhsTypeCode,
  1189. object rhs, TypeCode rhsTypeCode)
  1190. {
  1191. IConvertible lhsConvertible = (IConvertible)lhs;
  1192. IConvertible rhsConvertible = (IConvertible)rhs;
  1193. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1194. {
  1195. case TypeCode.Decimal:
  1196. return lhsConvertible.ToDecimal(null) % rhsConvertible.ToDecimal(null);
  1197. case TypeCode.Double:
  1198. return lhsConvertible.ToDouble(null) % rhsConvertible.ToDouble(null);
  1199. case TypeCode.Single:
  1200. return lhsConvertible.ToSingle(null) % rhsConvertible.ToSingle(null);
  1201. case TypeCode.UInt64:
  1202. return lhsConvertible.ToUInt64(null) % rhsConvertible.ToUInt64(null);
  1203. case TypeCode.Int64:
  1204. return lhsConvertible.ToInt64(null) % rhsConvertible.ToInt64(null);
  1205. case TypeCode.UInt32:
  1206. return lhsConvertible.ToUInt32(null) % rhsConvertible.ToUInt32(null);
  1207. default:
  1208. return lhsConvertible.ToInt32(null) % rhsConvertible.ToInt32(null);
  1209. }
  1210. }
  1211. private static double op_Exponentiation(object lhs, TypeCode lhsTypeCode, object rhs, TypeCode rhsTypeCode)
  1212. {
  1213. IConvertible lhsConvertible = (IConvertible)lhs;
  1214. IConvertible rhsConvertible = (IConvertible)rhs;
  1215. return Math.Pow(lhsConvertible.ToDouble(null), rhsConvertible.ToDouble(null));
  1216. }
  1217. private static object op_BitwiseAnd(object lhs, TypeCode lhsTypeCode,
  1218. object rhs, TypeCode rhsTypeCode)
  1219. {
  1220. IConvertible lhsConvertible = (IConvertible)lhs;
  1221. IConvertible rhsConvertible = (IConvertible)rhs;
  1222. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1223. {
  1224. case TypeCode.Decimal:
  1225. case TypeCode.Double:
  1226. case TypeCode.Single:
  1227. throw new ArgumentException(lhsTypeCode + " & " + rhsTypeCode);
  1228. case TypeCode.UInt64:
  1229. return lhsConvertible.ToUInt64(null) & rhsConvertible.ToUInt64(null);
  1230. case TypeCode.Int64:
  1231. return lhsConvertible.ToInt64(null) & rhsConvertible.ToInt64(null);
  1232. case TypeCode.UInt32:
  1233. return lhsConvertible.ToUInt32(null) & rhsConvertible.ToUInt32(null);
  1234. default:
  1235. return lhsConvertible.ToInt32(null) & rhsConvertible.ToInt32(null);
  1236. }
  1237. }
  1238. private static object op_BitwiseOr(object lhs, TypeCode lhsTypeCode,
  1239. object rhs, TypeCode rhsTypeCode)
  1240. {
  1241. IConvertible lhsConvertible = (IConvertible)lhs;
  1242. IConvertible rhsConvertible = (IConvertible)rhs;
  1243. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1244. {
  1245. case TypeCode.Decimal:
  1246. case TypeCode.Double:
  1247. case TypeCode.Single:
  1248. throw new ArgumentException(lhsTypeCode + " | " + rhsTypeCode);
  1249. case TypeCode.UInt64:
  1250. return lhsConvertible.ToUInt64(null) | rhsConvertible.ToUInt64(null);
  1251. case TypeCode.Int64:
  1252. return lhsConvertible.ToInt64(null) | rhsConvertible.ToInt64(null);
  1253. case TypeCode.UInt32:
  1254. return lhsConvertible.ToUInt32(null) | rhsConvertible.ToUInt32(null);
  1255. default:
  1256. return lhsConvertible.ToInt32(null) | rhsConvertible.ToInt32(null);
  1257. }
  1258. }
  1259. private static object op_ExclusiveOr(object lhs, TypeCode lhsTypeCode,
  1260. object rhs, TypeCode rhsTypeCode)
  1261. {
  1262. IConvertible lhsConvertible = (IConvertible)lhs;
  1263. IConvertible rhsConvertible = (IConvertible)rhs;
  1264. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1265. {
  1266. case TypeCode.Decimal:
  1267. case TypeCode.Double:
  1268. case TypeCode.Single:
  1269. throw new ArgumentException(lhsTypeCode + " ^ " + rhsTypeCode);
  1270. case TypeCode.UInt64:
  1271. return lhsConvertible.ToUInt64(null) ^ rhsConvertible.ToUInt64(null);
  1272. case TypeCode.Int64:
  1273. return lhsConvertible.ToInt64(null) ^ rhsConvertible.ToInt64(null);
  1274. case TypeCode.UInt32:
  1275. return lhsConvertible.ToUInt32(null) ^ rhsConvertible.ToUInt32(null);
  1276. default:
  1277. return lhsConvertible.ToInt32(null) ^ rhsConvertible.ToInt32(null);
  1278. }
  1279. }
  1280. private static object op_ShiftLeft(object lhs, TypeCode lhsTypeCode,
  1281. object rhs, TypeCode rhsTypeCode)
  1282. {
  1283. IConvertible lhsConvertible = (IConvertible)lhs;
  1284. IConvertible rhsConvertible = (IConvertible)rhs;
  1285. switch(rhsTypeCode)
  1286. {
  1287. case TypeCode.Decimal:
  1288. case TypeCode.Double:
  1289. case TypeCode.Single:
  1290. throw new ArgumentException(lhsTypeCode + " << " + rhsTypeCode);
  1291. default:
  1292. break;
  1293. }
  1294. switch (lhsTypeCode)
  1295. {
  1296. case TypeCode.Decimal:
  1297. case TypeCode.Double:
  1298. case TypeCode.Single:
  1299. throw new ArgumentException(lhsTypeCode + " << " + rhsTypeCode);
  1300. case TypeCode.UInt64:
  1301. return lhsConvertible.ToUInt64(null) << rhsConvertible.ToInt32(null);
  1302. case TypeCode.Int64:
  1303. return lhsConvertible.ToInt64(null) << rhsConvertible.ToInt32(null);
  1304. case TypeCode.UInt32:
  1305. return lhsConvertible.ToUInt32(null) << rhsConvertible.ToInt32(null);
  1306. default:
  1307. return lhsConvertible.ToInt32(null) << rhsConvertible.ToInt32(null);
  1308. }
  1309. }
  1310. private static object op_ShiftRight(object lhs, TypeCode lhsTypeCode,
  1311. object rhs, TypeCode rhsTypeCode)
  1312. {
  1313. IConvertible lhsConvertible = (IConvertible)lhs;
  1314. IConvertible rhsConvertible = (IConvertible)rhs;

Large files files are truncated, but you can click here to view the full file