PageRenderTime 53ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/w4x/boolangstudio
C# | 1698 lines | 1424 code | 202 blank | 72 comment | 260 complexity | 2b7b84363735b520ead137852f6024e3 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.Reflection;
  31. using System.Collections;
  32. using System.IO;
  33. using System.Reflection.Emit;
  34. using System.Text;
  35. namespace Boo.Lang.Runtime
  36. {
  37. public class RuntimeServices
  38. {
  39. private static readonly object[] NoArguments = new object[0];
  40. private static readonly Type RuntimeServicesType = typeof(RuntimeServices);
  41. internal const BindingFlags InstanceMemberFlags = BindingFlags.Public |
  42. BindingFlags.NonPublic |
  43. BindingFlags.Instance;
  44. internal const BindingFlags DefaultBindingFlags = InstanceMemberFlags |
  45. BindingFlags.OptionalParamBinding |
  46. BindingFlags.Static |
  47. BindingFlags.FlattenHierarchy;
  48. private const BindingFlags InvokeBindingFlags = DefaultBindingFlags |
  49. BindingFlags.InvokeMethod;
  50. private const BindingFlags StaticMemberBindingFlags = BindingFlags.Public |
  51. BindingFlags.Static |
  52. BindingFlags.FlattenHierarchy;
  53. private const BindingFlags InvokeOperatorBindingFlags = StaticMemberBindingFlags |
  54. BindingFlags.InvokeMethod;
  55. private const BindingFlags SetPropertyBindingFlags = DefaultBindingFlags |
  56. BindingFlags.SetProperty |
  57. BindingFlags.SetField;
  58. private const BindingFlags GetPropertyBindingFlags = DefaultBindingFlags |
  59. BindingFlags.GetProperty |
  60. BindingFlags.GetField;
  61. private static DispatcherCache _cache = new DispatcherCache();
  62. private static ExtensionRegistry _extensions = new ExtensionRegistry();
  63. public delegate void CodeBlock();
  64. public static void WithExtensions(System.Type extensions, CodeBlock block)
  65. {
  66. RegisterExtensions(extensions);
  67. try
  68. {
  69. block();
  70. }
  71. finally
  72. {
  73. UnRegisterExtensions(extensions);
  74. }
  75. }
  76. public static void RegisterExtensions(System.Type extensions)
  77. {
  78. _extensions.Register(extensions);
  79. }
  80. public static void UnRegisterExtensions(System.Type extensions)
  81. {
  82. _extensions.UnRegister(extensions);
  83. }
  84. public static object Invoke(object target, string name, object[] args)
  85. {
  86. return Dispatch(target, name, args, delegate { return CreateMethodDispatcher(target, name, args); });
  87. }
  88. private static Dispatcher CreateMethodDispatcher(object target, string name, object[] args)
  89. {
  90. IQuackFu duck = target as IQuackFu;
  91. if (null != duck)
  92. {
  93. return delegate(object o, object[] arguments) { return ((IQuackFu) o).QuackInvoke(name, arguments); };
  94. }
  95. Type type = target as Type;
  96. if (null != type)
  97. {
  98. // static method
  99. return DoCreateMethodDispatcher(null, type, name, args);
  100. }
  101. Type targetType = target.GetType();
  102. if (targetType.IsCOMObject)
  103. {
  104. // COM methods cant be seen through reflection
  105. // so maybe the proper way to support parameter conversions
  106. // is indeed by creating a specific Binder object
  107. // which knows the boo conversion rules
  108. return
  109. delegate(object o, object[] arguments) { return o.GetType().InvokeMember(name, InvokeBindingFlags, null, target, arguments); };
  110. }
  111. return DoCreateMethodDispatcher(target, targetType, name, args);
  112. }
  113. private static Dispatcher DoCreateMethodDispatcher(object target, Type targetType, string name, object[] args)
  114. {
  115. return new MethodDispatcherFactory(_extensions, target, targetType, name, args).Create();
  116. }
  117. private static object Dispatch(object target, string cacheKeyName, object[] args, DispatcherCache.DispatcherFactory factory)
  118. {
  119. Type[] cacheKeyTypes = MethodResolver.GetArgumentTypes(args);
  120. return Dispatch(target, cacheKeyName, cacheKeyTypes, args, factory);
  121. }
  122. private static object Dispatch(object target, string cacheKeyName, Type[] cacheKeyTypes, object[] args, DispatcherCache.DispatcherFactory factory)
  123. {
  124. Type targetType = (target as Type) ?? target.GetType();
  125. DispatcherKey key = new DispatcherKey(targetType, cacheKeyName, cacheKeyTypes);
  126. Dispatcher dispatcher = _cache.Get(key, factory);
  127. return dispatcher(target, args);
  128. }
  129. public static object GetProperty(object target, string name)
  130. {
  131. return Dispatch(target, name, NoArguments, delegate { return CreatePropGetDispatcher(target, name); });
  132. }
  133. private static Dispatcher CreatePropGetDispatcher(object target, string name)
  134. {
  135. IQuackFu duck = target as IQuackFu;
  136. if (null != duck)
  137. {
  138. return delegate(object o, object[] args) { return ((IQuackFu)o).QuackGet(name, null); };
  139. }
  140. Type type = target as Type;
  141. if (null != type) return DoCreatePropGetDispatcher(null, type, name);
  142. Type targetType = target.GetType();
  143. if (targetType.IsCOMObject)
  144. {
  145. return delegate(object o, object[] args)
  146. {
  147. return o.GetType().InvokeMember(name, GetPropertyBindingFlags, null, o, null);
  148. };
  149. }
  150. return DoCreatePropGetDispatcher(target, target.GetType(), name);
  151. }
  152. private static Dispatcher DoCreatePropGetDispatcher(object target, Type type, string name)
  153. {
  154. return new PropertyDispatcherFactory(_extensions, target, type, name).CreateGetter();
  155. }
  156. public static object SetProperty(object target, string name, object value)
  157. {
  158. return Dispatch(target, name, new object[] { value }, delegate { return CreatePropSetDispatcher(target, name, value); });
  159. }
  160. private static Dispatcher CreatePropSetDispatcher(object target, string name, object value)
  161. {
  162. IQuackFu duck = target as IQuackFu;
  163. if (null != duck)
  164. {
  165. return delegate(object o, object[] args) { return ((IQuackFu) o).QuackSet(name, null, args[0]); };
  166. }
  167. Type type = target as Type;
  168. if (null != type) return DoCreatePropSetDispatcher(null, type, name, value);
  169. Type targetType = target.GetType();
  170. if (targetType.IsCOMObject)
  171. {
  172. return delegate(object o, object[] args)
  173. {
  174. return o.GetType().InvokeMember(name,
  175. SetPropertyBindingFlags,
  176. null,
  177. o,
  178. args);
  179. };
  180. }
  181. return DoCreatePropSetDispatcher(target, targetType, name, value);
  182. }
  183. private static Dispatcher DoCreatePropSetDispatcher(object target, Type type, string name, object value)
  184. {
  185. return new PropertyDispatcherFactory(_extensions, target, type, name, value).CreateSetter();
  186. }
  187. public struct ValueTypeChange
  188. {
  189. public object Target;
  190. public string Member;
  191. public object Value;
  192. public ValueTypeChange(object target, string member, object value)
  193. {
  194. this.Target = target;
  195. this.Member = member;
  196. this.Value = value;
  197. }
  198. }
  199. public static void PropagateValueTypeChanges(ValueTypeChange[] changes)
  200. {
  201. foreach (ValueTypeChange change in changes)
  202. {
  203. if (!(change.Value is ValueType)) break;
  204. try
  205. {
  206. SetProperty(change.Target, change.Member, change.Value);
  207. }
  208. catch (System.MissingFieldException)
  209. {
  210. // hit a readonly property
  211. break;
  212. }
  213. }
  214. }
  215. [Obsolete("Use Coerce instead.")]
  216. public static object DuckImplicitCast(object value, Type toType)
  217. {
  218. return Coerce(value, toType);
  219. }
  220. public static object Coerce(object value, Type toType)
  221. {
  222. if (value == null) return null;
  223. return Dispatch(value, "$Coerce$", new Type[] {toType}, new object[] {toType}, delegate { return CreateCoerceDispatcher(value, toType); });
  224. }
  225. private static Dispatcher CreateCoerceDispatcher(object value, Type toType)
  226. {
  227. if (toType.IsInstanceOfType(value)) return IdentityDispatcher;
  228. if (value is ICoercible) return CoercibleDispatcher;
  229. Type fromType = value.GetType();
  230. if (IsPromotableNumeric(fromType) && IsPromotableNumeric(toType))
  231. {
  232. return new PromotionEmitter(toType).Emit();
  233. }
  234. MethodInfo method = FindImplicitConversionOperator(fromType, toType);
  235. if (null == method) return IdentityDispatcher;
  236. return EmitImplicitConversionDispatcher(method);
  237. }
  238. private static bool IsPromotableNumeric(Type fromType)
  239. {
  240. return IsPromotableNumeric(Type.GetTypeCode(fromType));
  241. }
  242. private static Dispatcher EmitImplicitConversionDispatcher(MethodInfo method)
  243. {
  244. return new ImplicitConversionEmitter(method).Emit();
  245. }
  246. private static object CoercibleDispatcher(object o, object[] args)
  247. {
  248. return ((ICoercible) o).Coerce((Type)args[0]);
  249. }
  250. private static object IdentityDispatcher(object o, object[] args)
  251. {
  252. return o;
  253. }
  254. public static object GetSlice(object target, string name, object[] args)
  255. {
  256. return Dispatch(target, name + "[]", args, delegate { return CreateGetSliceDispatcher(target, name, args); });
  257. }
  258. private static Dispatcher CreateGetSliceDispatcher(object target, string name, object[] args)
  259. {
  260. IQuackFu duck = target as IQuackFu;
  261. if (null != duck)
  262. {
  263. return delegate(object o, object[] arguments) { return ((IQuackFu) o).QuackGet(name, arguments); };
  264. }
  265. if ("" == name
  266. && args.Length == 1
  267. && target is System.Array) return GetArraySlice;
  268. return new SliceDispatcherFactory(_extensions, target, target.GetType(), name, args).CreateGetter();
  269. }
  270. private static object GetArraySlice(object target, object[] args)
  271. {
  272. IList list = (IList)target;
  273. return list[NormalizeIndex(list.Count, (int)args[0])];
  274. }
  275. public static object SetSlice(object target, string name, object[] args)
  276. {
  277. return Dispatch(target, name + "[]=", args, delegate { return CreateSetSliceDispatcher(target, name, args); });
  278. }
  279. static Dispatcher CreateSetSliceDispatcher(object target, string name, object[] args)
  280. {
  281. IQuackFu duck = target as IQuackFu;
  282. if (null != duck)
  283. {
  284. return delegate(object o, object[] arguments)
  285. {
  286. return ((IQuackFu) o).QuackSet(name, (object[]) GetRange2(arguments, 0, arguments.Length - 1), arguments[arguments.Length - 1]);
  287. };
  288. }
  289. if ("" == name
  290. && 2 == args.Length
  291. && target is System.Array) return SetArraySlice;
  292. return new SliceDispatcherFactory(_extensions, target, target.GetType(), name, args).CreateSetter();
  293. }
  294. private static object SetArraySlice(object target, object[] args)
  295. {
  296. IList list = (IList)target;
  297. list[NormalizeIndex(list.Count, (int)args[0])] = args[1];
  298. return args[1];
  299. }
  300. internal static String GetDefaultMemberName(Type type)
  301. {
  302. DefaultMemberAttribute attribute = (DefaultMemberAttribute)Attribute.GetCustomAttribute(type, typeof(DefaultMemberAttribute));
  303. return attribute != null ? attribute.MemberName : "";
  304. }
  305. public static object InvokeCallable(object target, object[] args)
  306. {
  307. if (null == target) throw new ArgumentNullException("target");
  308. if (null == args) throw new ArgumentNullException("args");
  309. ICallable c = target as ICallable;
  310. if (null != c) return c.Call(args);
  311. Delegate d = target as Delegate;
  312. if (null != d) return d.DynamicInvoke(args);
  313. Type type = target as Type;
  314. if (null != type) return Activator.CreateInstance(type, args);
  315. return ((MethodInfo)target).Invoke(null, args);
  316. }
  317. private static bool IsNumeric(TypeCode code)
  318. {
  319. switch (code)
  320. {
  321. case TypeCode.Byte: return true;
  322. case TypeCode.SByte: return true;
  323. case TypeCode.Int16: return true;
  324. case TypeCode.Int32: return true;
  325. case TypeCode.Int64: return true;
  326. case TypeCode.UInt16: return true;
  327. case TypeCode.UInt32: return true;
  328. case TypeCode.UInt64: return true;
  329. case TypeCode.Single: return true;
  330. case TypeCode.Double: return true;
  331. case TypeCode.Decimal: return true;
  332. }
  333. return false;
  334. }
  335. public static object InvokeBinaryOperator(string operatorName, object lhs, object rhs)
  336. {
  337. Type lhsType = lhs.GetType();
  338. Type rhsType = rhs.GetType();
  339. TypeCode lhsTypeCode = Type.GetTypeCode(lhsType);
  340. TypeCode rhsTypeCode = Type.GetTypeCode(rhsType);
  341. if (IsNumeric(lhsTypeCode) && IsNumeric(rhsTypeCode))
  342. {
  343. // HACK: optimization to get to the correct operators faster
  344. // is it worthy?
  345. switch (((int)operatorName[3] << 8) + (int)operatorName[operatorName.Length - 1])
  346. {
  347. case ((int)'A' << 8) + (int)'n': // op_Addition
  348. return op_Addition(lhs, lhsTypeCode, rhs, rhsTypeCode);
  349. case ((int)'S' << 8) + (int)'n': // op_Subtraction
  350. return op_Subtraction(lhs, lhsTypeCode, rhs, rhsTypeCode);
  351. case ((int)'M' << 8) + (int)'y': // op_Multiply
  352. return op_Multiply(lhs, lhsTypeCode, rhs, rhsTypeCode);
  353. case ((int)'D' << 8) + (int)'n': // op_Division
  354. return op_Division(lhs, lhsTypeCode, rhs, rhsTypeCode);
  355. case ((int)'M' << 8) + (int)'s': // op_Modulus
  356. return op_Modulus(lhs, lhsTypeCode, rhs, rhsTypeCode);
  357. case ((int)'E' << 8) + (int)'n': // op_Exponentiation
  358. return op_Exponentiation(lhs, lhsTypeCode, rhs, rhsTypeCode);
  359. case ((int)'L' << 8) + (int)'n': // op_LessThan
  360. return op_LessThan(lhs, lhsTypeCode, rhs, rhsTypeCode);
  361. case ((int)'L' << 8) + (int)'l': // op_LessThanOrEqual
  362. return op_LessThanOrEqual(lhs, lhsTypeCode, rhs, rhsTypeCode);
  363. case ((int)'G' << 8) + (int)'n': // op_GreaterThan
  364. return op_GreaterThan(lhs, lhsTypeCode, rhs, rhsTypeCode);
  365. case ((int)'G' << 8) + (int)'l': // op_GreaterThanOrEqual
  366. return op_GreaterThanOrEqual(lhs, lhsTypeCode, rhs, rhsTypeCode);
  367. case ((int)'B' << 8) + (int)'r': // op_BitwiseOr
  368. return op_BitwiseOr(lhs, lhsTypeCode, rhs, rhsTypeCode);
  369. case ((int)'B' << 8) + (int)'d': // op_BitwiseAnd
  370. return op_BitwiseAnd(lhs, lhsTypeCode, rhs, rhsTypeCode);
  371. case ((int)'M' << 8) + (int)'h': // op_Match
  372. case ((int)'N' << 8) + (int)'h': // op_NotMatch
  373. case ((int)'M' << 8) + (int)'r': // op_Member
  374. case ((int)'N' << 8) + (int)'r': // op_NotMember
  375. default:
  376. throw new ArgumentException(lhs + " " + operatorName + " " + rhs);
  377. }
  378. }
  379. else
  380. {
  381. object[] args = new object[] { lhs, rhs };
  382. IQuackFu duck = lhs as IQuackFu;
  383. if (null != duck)
  384. {
  385. return duck.QuackInvoke(operatorName, args);
  386. }
  387. else
  388. {
  389. duck = rhs as IQuackFu;
  390. if (null != duck)
  391. {
  392. return duck.QuackInvoke(operatorName, args);
  393. }
  394. }
  395. try
  396. {
  397. // TODO: first resolve the right method on either
  398. // lhs and rhs
  399. // and then cache the final information
  400. return Invoke(lhsType, operatorName, args);
  401. }
  402. catch (MissingMethodException)
  403. {
  404. try
  405. {
  406. return Invoke(rhsType, operatorName, args);
  407. }
  408. catch (MissingMethodException)
  409. {
  410. try
  411. {
  412. return InvokeRuntimeServicesOperator(operatorName, args);
  413. }
  414. catch (MissingMethodException)
  415. {
  416. }
  417. }
  418. throw; // always throw the original exception
  419. }
  420. }
  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. object[] args = new object[] { operand };
  441. IQuackFu duck = operand as IQuackFu;
  442. if (null != duck)
  443. {
  444. return duck.QuackInvoke(operatorName, args);
  445. }
  446. try
  447. {
  448. return Invoke(operandType, operatorName, args);
  449. }
  450. catch (MissingMethodException)
  451. {
  452. try
  453. {
  454. return InvokeRuntimeServicesOperator(operatorName, args);
  455. }
  456. catch (MissingMethodException)
  457. {
  458. }
  459. throw; // always throw the original exception
  460. }
  461. }
  462. }
  463. private static object InvokeRuntimeServicesOperator(string operatorName, object[] args)
  464. {
  465. return Invoke(RuntimeServicesType, operatorName, args);
  466. }
  467. public static object MoveNext(IEnumerator enumerator)
  468. {
  469. if (null == enumerator) Error("CantUnpackNull");
  470. if (!enumerator.MoveNext()) Error("UnpackListOfWrongSize");
  471. return enumerator.Current;
  472. }
  473. public static int Len(object obj)
  474. {
  475. if (null != obj)
  476. {
  477. ICollection collection = obj as ICollection;
  478. if (null != collection) return collection.Count;
  479. string s = obj as string;
  480. if (null != s) 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[] collapse)
  505. {
  506. if (dest.Rank != ranges.Length / 2)
  507. {
  508. throw new Exception("invalid range passed: " + ranges.Length / 2 + ", expected " + dest.Rank * 2);
  509. }
  510. for (int i = 0; i < dest.Rank; i++)
  511. {
  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. Error("InvalidArray");
  519. }
  520. }
  521. int sourceRank = 0;
  522. foreach (bool val in collapse)
  523. {
  524. if (!val)
  525. {
  526. sourceRank++;
  527. }
  528. }
  529. if (source.Rank != sourceRank)
  530. {
  531. // FIXME: Better error reporting
  532. Error("InvalidArray");
  533. }
  534. int[] lensDest = new int[dest.Rank];
  535. int[] lensSrc = new int[sourceRank];
  536. int rankIndex = 0;
  537. for (int i = 0; i < dest.Rank; i++)
  538. {
  539. lensDest[i] = ranges[2 * i + 1] - ranges[2 * i];
  540. if (!collapse[i])
  541. {
  542. lensSrc[rankIndex] = lensDest[i] - ranges[2 * i];
  543. if (lensSrc[rankIndex] != source.GetLength(rankIndex))
  544. {
  545. // FIXME: Better error reporting
  546. Error("InvalidArray");
  547. }
  548. rankIndex++;
  549. }
  550. }
  551. int[] modInd = new int[dest.Rank];
  552. for (int i = 0; i < dest.Rank; i++)
  553. {
  554. if (i == 0)
  555. {
  556. modInd[i] = source.Length / lensDest[lensDest.Length - 1];
  557. }
  558. else
  559. {
  560. modInd[i] = modInd[i - 1] / lensDest[i - 1];
  561. }
  562. }
  563. int counter;
  564. int[] indexDest = new int[dest.Rank];
  565. int[] indexSrc = new int[sourceRank];
  566. for (int i = 0; i < source.Length; i++)
  567. {
  568. counter = 0;
  569. for (int j = 0; j < dest.Rank; j++)
  570. {
  571. int index = (i % modInd[j]) / (modInd[j] / lensDest[j]);
  572. indexDest[j] = index;
  573. if (!collapse[j])
  574. {
  575. indexSrc[counter] = indexDest[j] + ranges[2 * j];
  576. counter++;
  577. }
  578. dest.SetValue(source.GetValue(indexSrc), indexDest);
  579. }
  580. }
  581. }
  582. public static Array GetMultiDimensionalRange1(Array source, int[] ranges, bool[] collapse)
  583. {
  584. int rankSrc = source.Rank;
  585. int collapseSize = 0;
  586. foreach (bool val in collapse)
  587. {
  588. if (val)
  589. {
  590. collapseSize++;
  591. }
  592. }
  593. int rankDest = rankSrc - collapseSize;
  594. int[] lensDest = new int[rankDest];
  595. int[] lensSrc = new int[rankSrc];
  596. int rankIndex = 0;
  597. for (int i = 0; i < rankSrc; i++)
  598. {
  599. ranges[2 * i] = NormalizeIndex(source.GetLength(i), ranges[2 * i]);
  600. ranges[2 * i + 1] = NormalizeIndex(source.GetLength(i), ranges[2 * i + 1]);
  601. lensSrc[i] = ranges[2 * i + 1] - ranges[2 * i];
  602. if (!collapse[i])
  603. {
  604. lensDest[rankIndex] = ranges[2 * i + 1] - ranges[2 * i];
  605. rankIndex++;
  606. }
  607. }
  608. Array dest = Array.CreateInstance(source.GetType().GetElementType(), lensDest);
  609. int[] modInd = new int[rankSrc];
  610. int[] indicesDest = new int[rankDest];
  611. int[] indicesSrc = new int[rankSrc];
  612. for (int i = 0; i < rankSrc; i++)
  613. {
  614. if (i == 0)
  615. {
  616. modInd[i] = dest.Length;
  617. }
  618. else
  619. {
  620. modInd[i] = modInd[i - 1] / lensSrc[i - 1];
  621. }
  622. }
  623. for (int i = 0; i < dest.Length; i++)
  624. {
  625. int destIndex = 0;
  626. for (int j = 0; j < rankSrc; j++)
  627. {
  628. int index = (i % modInd[j]) / (modInd[j] / lensSrc[j]);
  629. indicesSrc[j] = ranges[2 * j] + index;
  630. if (!collapse[j])
  631. {
  632. indicesDest[destIndex] = indicesSrc[j] - ranges[2 * j];
  633. destIndex++;
  634. }
  635. }
  636. dest.SetValue(source.GetValue(indicesSrc), indicesDest);
  637. }
  638. return dest;
  639. }
  640. public static void CheckArrayUnpack(Array array, int expected)
  641. {
  642. if (null == array)
  643. {
  644. Error("CantUnpackNull");
  645. }
  646. if (expected > array.Length)
  647. {
  648. Error("UnpackArrayOfWrongSize", expected, array.Length);
  649. }
  650. }
  651. public static int NormalizeIndex(int len, int index)
  652. {
  653. if (index < 0)
  654. {
  655. index += len;
  656. if (index < 0) return 0;
  657. }
  658. if (index > len) return len;
  659. return index;
  660. }
  661. public static int NormalizeArrayIndex(Array array, int index)
  662. {
  663. return NormalizeIndex(array.Length, index);
  664. }
  665. public static int NormalizeStringIndex(string s, int index)
  666. {
  667. return NormalizeIndex(s.Length, index);
  668. }
  669. public static IEnumerable GetEnumerable(object enumerable)
  670. {
  671. if (null == enumerable) Error("CantEnumerateNull");
  672. IEnumerable iterator = enumerable as IEnumerable;
  673. if (null != iterator) return iterator;
  674. TextReader reader = enumerable as TextReader;
  675. if (null != reader) return TextReaderEnumerator.lines(reader);
  676. Error("ArgumentNotEnumerable");
  677. return null;
  678. }
  679. #region global operators
  680. public static Array AddArrays(Type resultingElementType, Array lhs, Array rhs)
  681. {
  682. int resultingLen = lhs.Length + rhs.Length;
  683. Array result = Array.CreateInstance(resultingElementType, resultingLen);
  684. Array.Copy(lhs, 0, result, 0, lhs.Length);
  685. Array.Copy(rhs, 0, result, lhs.Length, rhs.Length);
  686. return result;
  687. }
  688. public static string op_Addition(string lhs, string rhs)
  689. {
  690. return string.Concat(lhs, rhs);
  691. }
  692. public static string op_Addition(string lhs, object rhs)
  693. {
  694. return string.Concat(lhs, rhs);
  695. }
  696. public static string op_Addition(object lhs, string rhs)
  697. {
  698. return string.Concat(lhs, rhs);
  699. }
  700. public static Array op_Multiply(Array lhs, int count)
  701. {
  702. if (count < 0)
  703. {
  704. throw new ArgumentOutOfRangeException("count");
  705. }
  706. Type type = lhs.GetType();
  707. if (1 != type.GetArrayRank())
  708. {
  709. throw new ArgumentException("lhs");
  710. }
  711. int length = lhs.Length;
  712. Array result = Array.CreateInstance(type.GetElementType(), length * count);
  713. int destinationIndex = 0;
  714. for (int i = 0; i < count; ++i)
  715. {
  716. Array.Copy(lhs, 0, result, destinationIndex, length);
  717. destinationIndex += length;
  718. }
  719. return result;
  720. }
  721. public static Array op_Multiply(int count, Array rhs)
  722. {
  723. return op_Multiply(rhs, count);
  724. }
  725. public static string op_Multiply(string lhs, int count)
  726. {
  727. if (count < 0)
  728. {
  729. throw new ArgumentOutOfRangeException("count");
  730. }
  731. string result = null;
  732. if (null != lhs)
  733. {
  734. StringBuilder builder = new StringBuilder(lhs.Length * count);
  735. for (int i = 0; i < count; ++i)
  736. {
  737. builder.Append(lhs);
  738. }
  739. result = builder.ToString();
  740. }
  741. return result;
  742. }
  743. public static string op_Multiply(int count, string rhs)
  744. {
  745. return op_Multiply(rhs, count);
  746. }
  747. public static bool op_NotMember(string lhs, string rhs)
  748. {
  749. return !op_Member(lhs, rhs);
  750. }
  751. public static bool op_Member(string lhs, string rhs)
  752. {
  753. if (null == lhs || null == rhs)
  754. {
  755. return false;
  756. }
  757. return rhs.IndexOf(lhs) > -1;
  758. }
  759. #if !NO_SYSTEM_DLL
  760. public static bool op_Match(string input, System.Text.RegularExpressions.Regex pattern)
  761. {
  762. return pattern.IsMatch(input);
  763. }
  764. public static bool op_Match(string input, string pattern)
  765. {
  766. return System.Text.RegularExpressions.Regex.IsMatch(input, pattern);
  767. }
  768. public static bool op_NotMatch(string input, string pattern)
  769. {
  770. return !op_Match(input, pattern);
  771. }
  772. #endif
  773. public static string op_Modulus(string lhs, IEnumerable rhs)
  774. {
  775. return string.Format(lhs, Boo.Lang.Builtins.array(rhs));
  776. }
  777. public static string op_Modulus(string lhs, object[] rhs)
  778. {
  779. return string.Format(lhs, rhs);
  780. }
  781. public static bool op_Member(object lhs, IList rhs)
  782. {
  783. if (null == rhs)
  784. {
  785. return false;
  786. }
  787. return rhs.Contains(lhs);
  788. }
  789. public static bool op_NotMember(object lhs, IList rhs)
  790. {
  791. return !op_Member(lhs, rhs);
  792. }
  793. public static bool op_Member(object lhs, IDictionary rhs)
  794. {
  795. if (null == rhs)
  796. {
  797. return false;
  798. }
  799. return rhs.Contains(lhs);
  800. }
  801. public static bool op_NotMember(object lhs, IDictionary rhs)
  802. {
  803. return !op_Member(lhs, rhs);
  804. }
  805. public static bool op_Member(object lhs, IEnumerable rhs)
  806. {
  807. if (null == rhs)
  808. {
  809. return false;
  810. }
  811. foreach (object item in rhs)
  812. {
  813. if (EqualityOperator(lhs, item))
  814. {
  815. return true;
  816. }
  817. }
  818. return false;
  819. }
  820. public static bool op_NotMember(object lhs, IEnumerable rhs)
  821. {
  822. return !op_Member(lhs, rhs);
  823. }
  824. public static bool EqualityOperator(object lhs, object rhs)
  825. {
  826. if (lhs == rhs) return true;
  827. // Some types do overload Equals to compare
  828. // against null values
  829. if (null == lhs) return rhs.Equals(lhs);
  830. if (null == rhs) return lhs.Equals(rhs);
  831. TypeCode lhsTypeCode = Type.GetTypeCode(lhs.GetType());
  832. TypeCode rhsTypeCode = Type.GetTypeCode(rhs.GetType());
  833. if (IsNumeric(lhsTypeCode) && IsNumeric(rhsTypeCode))
  834. {
  835. return EqualityOperator(lhs, lhsTypeCode, rhs, rhsTypeCode);
  836. }
  837. Array lhsa = lhs as Array;
  838. if (null != lhsa)
  839. {
  840. Array rhsa = rhs as Array;
  841. if (null != rhsa)
  842. {
  843. return ArrayEqualityImpl(lhsa, rhsa);
  844. }
  845. }
  846. return lhs.Equals(rhs) || rhs.Equals(lhs);
  847. }
  848. public static bool op_Equality(Array lhs, Array rhs)
  849. {
  850. if (lhs == rhs)
  851. {
  852. return true;
  853. }
  854. if (null == lhs || null == rhs)
  855. {
  856. return false;
  857. }
  858. return ArrayEqualityImpl(lhs, rhs);
  859. }
  860. static bool ArrayEqualityImpl(Array lhs, Array rhs)
  861. {
  862. if (1 != lhs.Rank || 1 != rhs.Rank)
  863. {
  864. throw new ArgumentException("array rank must be 1");
  865. }
  866. if (lhs.Length != rhs.Length)
  867. {
  868. return false;
  869. }
  870. for (int i = 0; i < lhs.Length; ++i)
  871. {
  872. if (!EqualityOperator(lhs.GetValue(i), rhs.GetValue(i)))
  873. {
  874. return false;
  875. }
  876. }
  877. return true;
  878. }
  879. #endregion
  880. #region dynamic operator for primitive types
  881. private static TypeCode GetConvertTypeCode(TypeCode lhsTypeCode, TypeCode rhsTypeCode)
  882. {
  883. /* C# ECMA Spec V2
  884. * 14.2.6.2 Binary numeric promotions
  885. * This clause is informative.
  886. * Binary numeric promotion occurs for the operands of the predefined +, ?, *, /, %, &, |, ^, ==, !=, >, <, >=,
  887. * and <= binary operators. Binary numeric promotion implicitly converts both operands to a common type
  888. * which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric
  889. * promotion consists of applying the following rules, in the order they appear here:
  890. * � If either operand is of type decimal, the other operand is converted to type decimal, or a compiletime
  891. * error occurs if the other operand is of type float or double.
  892. * � Otherwise, if either operand is of type double, the other operand is converted to type double.
  893. * � Otherwise, if either operand is of type float, the other operand is converted to type float.
  894. * � Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a
  895. * compile-time error occurs if the other operand is of type sbyte, short, int, or long.
  896. * � Otherwise, if either operand is of type long, the other operand is converted to type long.
  897. * � Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int,
  898. * both operands are converted to type long.
  899. * � Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  900. * � Otherwise, both operands are converted to type int.
  901. * [Note: The first rule disallows any operations that mix the decimal type with the double and float types.
  902. * The rule follows from the fact that there are no implicit conversions between the decimal type and the
  903. * double and float types. end note]
  904. * [Note: Also note that it is not possible for an operand to be of type ulong when the other operand is of a
  905. * signed integral type. The reason is that no integral type exists that can represent the full range of ulong as
  906. * well as the signed integral types. end note]
  907. * In both of the above cases, a cast expression can be used to explicitly convert one operand to a type that is
  908. * compatible with the other operand.
  909. */
  910. if (TypeCode.Decimal == lhsTypeCode || TypeCode.Decimal == rhsTypeCode)
  911. {
  912. return TypeCode.Decimal; // not per ECMA spec
  913. }
  914. if (TypeCode.Double == lhsTypeCode || TypeCode.Double == rhsTypeCode)
  915. {
  916. return TypeCode.Double;
  917. }
  918. if (TypeCode.Single == lhsTypeCode || TypeCode.Single == rhsTypeCode)
  919. {
  920. return TypeCode.Single;
  921. }
  922. if (TypeCode.UInt64 == lhsTypeCode)
  923. {
  924. if (TypeCode.SByte == rhsTypeCode || TypeCode.Int16 == rhsTypeCode ||
  925. TypeCode.Int32 == rhsTypeCode || TypeCode.Int64 == rhsTypeCode)
  926. {
  927. // throw new ArgumentException("ulong <op> " + rhsTypeCode);
  928. return TypeCode.Int64; // not per Ecma spec
  929. }
  930. return TypeCode.UInt64;
  931. }
  932. if (TypeCode.UInt64 == rhsTypeCode)
  933. {
  934. if (TypeCode.SByte == lhsTypeCode || TypeCode.Int16 == lhsTypeCode ||
  935. TypeCode.Int32 == lhsTypeCode || TypeCode.Int64 == lhsTypeCode)
  936. {
  937. // throw new ArgumentException(lhsTypeCode + " <op> ulong");
  938. return TypeCode.Int64; // not per Ecma spec
  939. }
  940. return TypeCode.UInt64;
  941. }
  942. if (TypeCode.Int64 == lhsTypeCode || TypeCode.Int64 == rhsTypeCode)
  943. {
  944. return TypeCode.Int64;
  945. }
  946. if (TypeCode.UInt32 == lhsTypeCode)
  947. {
  948. if (TypeCode.SByte == rhsTypeCode || TypeCode.Int16 == rhsTypeCode ||
  949. TypeCode.Int32 == rhsTypeCode)
  950. {
  951. return TypeCode.Int64;
  952. }
  953. return TypeCode.UInt32;
  954. }
  955. if (TypeCode.UInt32 == rhsTypeCode)
  956. {
  957. if (TypeCode.SByte == lhsTypeCode || TypeCode.Int16 == lhsTypeCode ||
  958. TypeCode.Int32 == lhsTypeCode)
  959. {
  960. return TypeCode.Int64;
  961. }
  962. return TypeCode.UInt32;
  963. }
  964. return TypeCode.Int32;
  965. }
  966. private static object op_Multiply(object lhs, TypeCode lhsTypeCode,
  967. object rhs, TypeCode rhsTypeCode)
  968. {
  969. IConvertible lhsConvertible = (IConvertible)lhs;
  970. IConvertible rhsConvertible = (IConvertible)rhs;
  971. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  972. {
  973. case TypeCode.Decimal:
  974. return lhsConvertible.ToDecimal(null) * rhsConvertible.ToDecimal(null);
  975. case TypeCode.Double:
  976. return lhsConvertible.ToDouble(null) * rhsConvertible.ToDouble(null);
  977. case TypeCode.Single:
  978. return lhsConvertible.ToSingle(null) * rhsConvertible.ToSingle(null);
  979. case TypeCode.UInt64:
  980. return lhsConvertible.ToUInt64(null) * rhsConvertible.ToUInt64(null);
  981. case TypeCode.Int64:
  982. return lhsConvertible.ToInt64(null) * rhsConvertible.ToInt64(null);
  983. case TypeCode.UInt32:
  984. return lhsConvertible.ToUInt32(null) * rhsConvertible.ToUInt32(null);
  985. case TypeCode.Int32:
  986. default:
  987. return lhsConvertible.ToInt32(null) * rhsConvertible.ToInt32(null);
  988. }
  989. }
  990. private static object op_Division(object lhs, TypeCode lhsTypeCode,
  991. object rhs, TypeCode rhsTypeCode)
  992. {
  993. IConvertible lhsConvertible = (IConvertible)lhs;
  994. IConvertible rhsConvertible = (IConvertible)rhs;
  995. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  996. {
  997. case TypeCode.Decimal:
  998. return lhsConvertible.ToDecimal(null) / rhsConvertible.ToDecimal(null);
  999. case TypeCode.Double:
  1000. return lhsConvertible.ToDouble(null) / rhsConvertible.ToDouble(null);
  1001. case TypeCode.Single:
  1002. return lhsConvertible.ToSingle(null) / rhsConvertible.ToSingle(null);
  1003. case TypeCode.UInt64:
  1004. return lhsConvertible.ToUInt64(null) / rhsConvertible.ToUInt64(null);
  1005. case TypeCode.Int64:
  1006. return lhsConvertible.ToInt64(null) / rhsConvertible.ToInt64(null);
  1007. case TypeCode.UInt32:
  1008. return lhsConvertible.ToUInt32(null) / rhsConvertible.ToUInt32(null);
  1009. case TypeCode.Int32:
  1010. default:
  1011. return lhsConvertible.ToInt32(null) / rhsConvertible.ToInt32(null);
  1012. }
  1013. }
  1014. private static object op_Addition(object lhs, TypeCode lhsTypeCode,
  1015. object rhs, TypeCode rhsTypeCode)
  1016. {
  1017. IConvertible lhsConvertible = (IConvertible)lhs;
  1018. IConvertible rhsConvertible = (IConvertible)rhs;
  1019. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1020. {
  1021. case TypeCode.Decimal:
  1022. return lhsConvertible.ToDecimal(null) + rhsConvertible.ToDecimal(null);
  1023. case TypeCode.Double:
  1024. return lhsConvertible.ToDouble(null) + rhsConvertible.ToDouble(null);
  1025. case TypeCode.Single:
  1026. return lhsConvertible.ToSingle(null) + rhsConvertible.ToSingle(null);
  1027. case TypeCode.UInt64:
  1028. return lhsConvertible.ToUInt64(null) + rhsConvertible.ToUInt64(null);
  1029. case TypeCode.Int64:
  1030. return lhsConvertible.ToInt64(null) + rhsConvertible.ToInt64(null);
  1031. case TypeCode.UInt32:
  1032. return lhsConvertible.ToUInt32(null) + rhsConvertible.ToUInt32(null);
  1033. case TypeCode.Int32:
  1034. default:
  1035. return lhsConvertible.ToInt32(null) + rhsConvertible.ToInt32(null);
  1036. }
  1037. }
  1038. private static object op_Subtraction(object lhs, TypeCode lhsTypeCode,
  1039. object rhs, TypeCode rhsTypeCode)
  1040. {
  1041. IConvertible lhsConvertible = (IConvertible)lhs;
  1042. IConvertible rhsConvertible = (IConvertible)rhs;
  1043. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1044. {
  1045. case TypeCode.Decimal:
  1046. return lhsConvertible.ToDecimal(null) - rhsConvertible.ToDecimal(null);
  1047. case TypeCode.Double:
  1048. return lhsConvertible.ToDouble(null) - rhsConvertible.ToDouble(null);
  1049. case TypeCode.Single:
  1050. return lhsConvertible.ToSingle(null) - rhsConvertible.ToSingle(null);
  1051. case TypeCode.UInt64:
  1052. return lhsConvertible.ToUInt64(null) - rhsConvertible.ToUInt64(null);
  1053. case TypeCode.Int64:
  1054. return lhsConvertible.ToInt64(null) - rhsConvertible.ToInt64(null);
  1055. case TypeCode.UInt32:
  1056. return lhsConvertible.ToUInt32(null) - rhsConvertible.ToUInt32(null);
  1057. case TypeCode.Int32:
  1058. default:
  1059. return lhsConvertible.ToInt32(null) - rhsConvertible.ToInt32(null);
  1060. }
  1061. }
  1062. private static bool EqualityOperator(object lhs, TypeCode lhsTypeCode,
  1063. object rhs, TypeCode rhsTypeCode)
  1064. {
  1065. IConvertible lhsConvertible = (IConvertible)lhs;
  1066. IConvertible rhsConvertible = (IConvertible)rhs;
  1067. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1068. {
  1069. case TypeCode.Decimal:
  1070. return lhsConvertible.ToDecimal(null) == rhsConvertible.ToDecimal(null);
  1071. case TypeCode.Double:
  1072. return lhsConvertible.ToDouble(null) == rhsConvertible.ToDouble(null);
  1073. case TypeCode.Single:
  1074. return lhsConvertible.ToSingle(null) == rhsConvertible.ToSingle(null);
  1075. case TypeCode.UInt64:
  1076. return lhsConvertible.ToUInt64(null) == rhsConvertible.ToUInt64(null);
  1077. case TypeCode.Int64:
  1078. return lhsConvertible.ToInt64(null) == rhsConvertible.ToInt64(null);
  1079. case TypeCode.UInt32:
  1080. return lhsConvertible.ToUInt32(null) == rhsConvertible.ToUInt32(null);
  1081. case TypeCode.Int32:
  1082. default:
  1083. return lhsConvertible.ToInt32(null) == rhsConvertible.ToInt32(null);
  1084. }
  1085. }
  1086. private static bool op_GreaterThan(object lhs, TypeCode lhsTypeCode,
  1087. object rhs, TypeCode rhsTypeCode)
  1088. {
  1089. IConvertible lhsConvertible = (IConvertible)lhs;
  1090. IConvertible rhsConvertible = (IConvertible)rhs;
  1091. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1092. {
  1093. case TypeCode.Decimal:
  1094. return lhsConvertible.ToDecimal(null) > rhsConvertible.ToDecimal(null);
  1095. case TypeCode.Double:
  1096. return lhsConvertible.ToDouble(null) > rhsConvertible.ToDouble(null);
  1097. case TypeCode.Single:
  1098. return lhsConvertible.ToSingle(null) > rhsConvertible.ToSingle(null);
  1099. case TypeCode.UInt64:
  1100. return lhsConvertible.ToUInt64(null) > rhsConvertible.ToUInt64(null);
  1101. case TypeCode.Int64:
  1102. return lhsConvertible.ToInt64(null) > rhsConvertible.ToInt64(null);
  1103. case TypeCode.UInt32:
  1104. return lhsConvertible.ToUInt32(null) > rhsConvertible.ToUInt32(null);
  1105. case TypeCode.Int32:
  1106. default:
  1107. return lhsConvertible.ToInt32(null) > rhsConvertible.ToInt32(null);
  1108. }
  1109. }
  1110. private static bool op_GreaterThanOrEqual(object lhs, TypeCode lhsTypeCode,
  1111. object rhs, TypeCode rhsTypeCode)
  1112. {
  1113. IConvertible lhsConvertible = (IConvertible)lhs;
  1114. IConvertible rhsConvertible = (IConvertible)rhs;
  1115. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1116. {
  1117. case TypeCode.Decimal:
  1118. return lhsConvertible.ToDecimal(null) >= rhsConvertible.ToDecimal(null);
  1119. case TypeCode.Double:
  1120. return lhsConvertible.ToDouble(null) >= rhsConvertible.ToDouble(null);
  1121. case TypeCode.Single:
  1122. return lhsConvertible.ToSingle(null) >= rhsConvertible.ToSingle(null);
  1123. case TypeCode.UInt64:
  1124. return lhsConvertible.ToUInt64(null) >= rhsConvertible.ToUInt64(null);
  1125. case TypeCode.Int64:
  1126. return lhsConvertible.ToInt64(null) >= rhsConvertible.ToInt64(null);
  1127. case TypeCode.UInt32:
  1128. return lhsConvertible.ToUInt32(null) >= rhsConvertible.ToUInt32(null);
  1129. case TypeCode.Int32:
  1130. default:
  1131. return lhsConvertible.ToInt32(null) >= rhsConvertible.ToInt32(null);
  1132. }
  1133. }
  1134. private static bool op_LessThan(object lhs, TypeCode lhsTypeCode,
  1135. object rhs, TypeCode rhsTypeCode)
  1136. {
  1137. IConvertible lhsConvertible = (IConvertible)lhs;
  1138. IConvertible rhsConvertible = (IConvertible)rhs;
  1139. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1140. {
  1141. case TypeCode.Decimal:
  1142. return lhsConvertible.ToDecimal(null) < rhsConvertible.ToDecimal(null);
  1143. case TypeCode.Double:
  1144. return lhsConvertible.ToDouble(null) < rhsConvertible.ToDouble(null);
  1145. case TypeCode.Single:
  1146. return lhsConvertible.ToSingle(null) < rhsConvertible.ToSingle(null);
  1147. case TypeCode.UInt64:
  1148. return lhsConvertible.ToUInt64(null) < rhsConvertible.ToUInt64(null);
  1149. case TypeCode.Int64:
  1150. return lhsConvertible.ToInt64(null) < rhsConvertible.ToInt64(null);
  1151. case TypeCode.UInt32:
  1152. return lhsConvertible.ToUInt32(null) < rhsConvertible.ToUInt32(null);
  1153. case TypeCode.Int32:
  1154. default:
  1155. return lhsConvertible.ToInt32(null) < rhsConvertible.ToInt32(null);
  1156. }
  1157. }
  1158. private static bool op_LessThanOrEqual(object lhs, TypeCode lhsTypeCode,
  1159. object rhs, TypeCode rhsTypeCode)
  1160. {
  1161. IConvertible lhsConvertible = (IConvertible)lhs;
  1162. IConvertible rhsConvertible = (IConvertible)rhs;
  1163. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1164. {
  1165. case TypeCode.Decimal:
  1166. return lhsConvertible.ToDecimal(null) <= rhsConvertible.ToDecimal(null);
  1167. case TypeCode.Double:
  1168. return lhsConvertible.ToDouble(null) <= rhsConvertible.ToDouble(null);
  1169. case TypeCode.Single:
  1170. return lhsConvertible.ToSingle(null) <= rhsConvertible.ToSingle(null);
  1171. case TypeCode.UInt64:
  1172. return lhsConvertible.ToUInt64(null) <= rhsConvertible.ToUInt64(null);
  1173. case TypeCode.Int64:
  1174. return lhsConvertible.ToInt64(null) <= rhsConvertible.ToInt64(null);
  1175. case TypeCode.UInt32:
  1176. return lhsConvertible.ToUInt32(null) <= rhsConvertible.ToUInt32(null);
  1177. case TypeCode.Int32:
  1178. default:
  1179. return lhsConvertible.ToInt32(null) <= rhsConvertible.ToInt32(null);
  1180. }
  1181. }
  1182. private static object op_Modulus(object lhs, TypeCode lhsTypeCode,
  1183. object rhs, TypeCode rhsTypeCode)
  1184. {
  1185. IConvertible lhsConvertible = (IConvertible)lhs;
  1186. IConvertible rhsConvertible = (IConvertible)rhs;
  1187. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1188. {
  1189. case TypeCode.Decimal:
  1190. return lhsConvertible.ToDecimal(null) % rhsConvertible.ToDecimal(null);
  1191. case TypeCode.Double:
  1192. return lhsConvertible.ToDouble(null) % rhsConvertible.ToDouble(null);
  1193. case TypeCode.Single:
  1194. return lhsConvertible.ToSingle(null) % rhsConvertible.ToSingle(null);
  1195. case TypeCode.UInt64:
  1196. return lhsConvertible.ToUInt64(null) % rhsConvertible.ToUInt64(null);
  1197. case TypeCode.Int64:
  1198. return lhsConvertible.ToInt64(null) % rhsConvertible.ToInt64(null);
  1199. case TypeCode.UInt32:
  1200. return lhsConvertible.ToUInt32(null) % rhsConvertible.ToUInt32(null);
  1201. case TypeCode.Int32:
  1202. default:
  1203. return lhsConvertible.ToInt32(null) % rhsConvertible.ToInt32(null);
  1204. }
  1205. }
  1206. private static double op_Exponentiation(object lhs, TypeCode lhsTypeCode,
  1207. object rhs, TypeCode rhsTypeCode)
  1208. {
  1209. IConvertible lhsConvertible = (IConvertible)lhs;
  1210. IConvertible rhsConvertible = (IConvertible)rhs;
  1211. return Math.Pow(lhsConvertible.ToDouble(null), rhsConvertible.ToDouble(null));
  1212. }
  1213. private static object op_BitwiseAnd(object lhs, TypeCode lhsTypeCode,
  1214. object rhs, TypeCode rhsTypeCode)
  1215. {
  1216. IConvertible lhsConvertible = (IConvertible)lhs;
  1217. IConvertible rhsConvertible = (IConvertible)rhs;
  1218. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1219. {
  1220. case TypeCode.Decimal:
  1221. case TypeCode.Double:
  1222. case TypeCode.Single:
  1223. throw new ArgumentException(lhsTypeCode + " & " + rhsTypeCode);
  1224. case TypeCode.UInt64:
  1225. return lhsConvertible.ToUInt64(null) & rhsConvertible.ToUInt64(null);
  1226. case TypeCode.Int64:
  1227. return lhsConvertible.ToInt64(null) & rhsConvertible.ToInt64(null);
  1228. case TypeCode.UInt32:
  1229. return lhsConvertible.ToUInt32(null) & rhsConvertible.ToUInt32(null);
  1230. case TypeCode.Int32:
  1231. default:
  1232. return lhsConvertible.ToInt32(null) & rhsConvertible.ToInt32(null);
  1233. }
  1234. }
  1235. private static object op_BitwiseOr(object lhs, TypeCode lhsTypeCode,
  1236. object rhs, TypeCode rhsTypeCode)
  1237. {
  1238. IConvertible lhsConvertible = (IConvertible)lhs;
  1239. IConvertible rhsConvertible = (IConvertible)rhs;
  1240. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1241. {
  1242. case TypeCode.Decimal:
  1243. case TypeCode.Double:
  1244. case TypeCode.Single:
  1245. throw new ArgumentException(lhsTypeCode + " | " + rhsTypeCode);
  1246. case TypeCode.UInt64:
  1247. return lhsConvertible.ToUInt64(null) | rhsConvertible.ToUInt64(null);
  1248. case TypeCode.Int64:
  1249. return lhsConvertible.ToInt64(null) | rhsConvertible.ToInt64(null);
  1250. case TypeCode.UInt32:
  1251. return lhsConvertible.ToUInt32(null) | rhsConvertible.ToUInt32(null);
  1252. case TypeCode.Int32:
  1253. default:
  1254. return lhsConvertible.ToInt32(null) | rhsConvertible.ToInt32(null);
  1255. }
  1256. }
  1257. private static object op_UnaryNegation(object operand, TypeCode operandTypeCode)
  1258. {
  1259. IConvertible operandConvertible = (IConvertible)operand;
  1260. switch (operandTypeCode)
  1261. {
  1262. case TypeCode.Decimal:
  1263. return -operandConvertible.ToDecimal(null);
  1264. case TypeCode.Double:
  1265. return -operandConvertible.ToDouble(null);
  1266. case TypeCode.Single:
  1267. return -operandConvertible.ToSingle(null);
  1268. case TypeCode.UInt64:
  1269. return -operandConvertible.ToInt64(null);
  1270. case TypeCode.Int64:
  1271. return -operandConvertible.ToInt64(null);
  1272. case TypeCode.UInt32:
  1273. return -operandConvertible.ToInt64(null);
  1274. case TypeCode.Int32:
  1275. default:
  1276. return -operandConvertible.ToInt32(null);
  1277. }
  1278. }
  1279. #endregion
  1280. internal static bool IsPromotableNumeric(TypeCode code)
  1281. {
  1282. switch (code)
  1283. {
  1284. case TypeCode.Byte: return true;
  1285. case TypeCode.SByte: return true;
  1286. case TypeCode.Int16: return true;
  1287. case TypeCode.Int32: return true;
  1288. case TypeCode.Int64: return true;
  1289. case TypeCode.UInt16: return true;
  1290. case TypeCode.UInt32: return true;
  1291. case TypeCode.UInt64: return true;
  1292. case TypeCode.Single: return true;
  1293. case TypeCode.Double: return true;
  1294. case TypeCode.Boolean: return true;
  1295. case TypeCode.Decimal: return true;
  1296. case TypeCode.Char: return true;
  1297. }
  1298. return false;
  1299. }
  1300. public static IConvertible CheckNumericPromotion(object value)
  1301. {
  1302. IConvertible convertible = (IConvertible)value;
  1303. return CheckNumericPromotion(convertible);
  1304. }
  1305. public static IConvertible CheckNumericPromotion(IConvertible convertible)
  1306. {
  1307. if (IsPromotableNumeric(convertible.GetTypeCode()))
  1308. {
  1309. return convertible;
  1310. }
  1311. throw new InvalidCastException();
  1312. }
  1313. public static Byte UnboxByte(object value)
  1314. {
  1315. if (value is Byte)
  1316. {
  1317. return (Byte)value;
  1318. }
  1319. return CheckNumericPromotion(value).ToByte(null);
  1320. }
  1321. public static SByte UnboxSByte(object value)
  1322. {
  1323. if (value is SByte)
  1324. {
  1325. return (SByte)value;
  1326. }
  1327. return CheckNumericPromotion(value).ToSByte(null);
  1328. }
  1329. public static char UnboxChar(object value)
  1330. {
  1331. if (value is char)
  1332. {
  1333. return (char)value;
  1334. }
  1335. return CheckNumericPromotion(value).ToChar(null);
  1336. }
  1337. public static Int16 UnboxInt16(object value)
  1338. {
  1339. if (value is Int16)
  1340. {
  1341. return (Int16)value;
  1342. }
  1343. return CheckNumericPromotion(value).ToInt16(null);
  1344. }
  1345. public static UInt16 UnboxUInt16(object value)
  1346. {
  1347. if (value is UInt16)
  1348. {
  1349. return (UInt16)value;
  1350. }
  1351. return CheckNumericPromotion(value).ToUInt16(null);
  1352. }
  1353. public static Int32 UnboxInt32(object value)
  1354. {
  1355. if (value is Int32)
  1356. {
  1357. return (Int32)value;
  1358. }
  1359. return CheckNumericPromotion(value).ToInt32(null);
  1360. }
  1361. public static UInt32 UnboxUInt32(object value)
  1362. {
  1363. if (value is UInt32)
  1364. {
  1365. return (UInt32)value;
  1366. }
  1367. return CheckNumericPromotion(value).ToUInt32(null);
  1368. }
  1369. public static Int64 UnboxInt64(object value)
  1370. {
  1371. if (value is Int64)
  1372. {
  1373. return (Int64)value;
  1374. }
  1375. return CheckNumericPromotion(value).ToInt64(null);
  1376. }
  1377. public static UInt64 UnboxUInt64(object value)
  1378. {
  1379. if (value is UInt64)
  1380. {
  1381. return (UInt64)value;
  1382. }
  1383. return CheckNumericPromotion(value).ToUInt64(null);
  1384. }
  1385. public static Single UnboxSingle(object value)
  1386. {
  1387. if (value is Single)
  1388. {
  1389. return (Single)value;
  1390. }
  1391. return CheckNumericPromotion(value).ToSingle(null);
  1392. }
  1393. public static Double UnboxDouble(object value)
  1394. {
  1395. if (value is Double)
  1396. {
  1397. return (Double)value;
  1398. }
  1399. return CheckNumericPromotion(value).ToDouble(null);
  1400. }
  1401. public static Decimal UnboxDecimal(object value)
  1402. {
  1403. if (value is Decimal)
  1404. {
  1405. return (Decimal)value;
  1406. }
  1407. return CheckNumericPromotion(value).ToDecimal(null);
  1408. }
  1409. public static Boolean UnboxBoolean(object value)
  1410. {
  1411. if (value is Boolean)
  1412. {
  1413. return (Boolean)value;
  1414. }
  1415. return CheckNumericPromotion(value).ToBoolean(null);
  1416. }
  1417. #region bool conversion
  1418. public static bool ToBool(object value)
  1419. {
  1420. if (null == value) return false;
  1421. if (value is bool) return (bool) value;
  1422. Type type = value.GetType();
  1423. return
  1424. (bool)
  1425. Dispatch(value, "$ToBool$", new Type[] {type}, new object[] {value}, delegate { return CreateBoolConverter(type); });
  1426. }
  1427. public static bool ToBool(decimal value)
  1428. {
  1429. return 0 != value;
  1430. }
  1431. public static bool ToBool(System.Single value)
  1432. {
  1433. return 0 != value;
  1434. }
  1435. public static bool ToBool(System.Double value)
  1436. {
  1437. return 0 != value;
  1438. }
  1439. private static readonly object True = true;
  1440. private static object ToBoolTrue(object value, object[] arguments)
  1441. {
  1442. return True;
  1443. }
  1444. private static object UnboxBooleanDispatcher(object value, object[] arguments)
  1445. {
  1446. return UnboxBoolean(value);
  1447. }
  1448. static Dispatcher CreateBoolConverter(Type type)
  1449. {
  1450. MethodInfo method = FindImplicitConversionOperator(type, typeof(bool));
  1451. if (null != method) return EmitImplicitConversionDispatcher(method);
  1452. if (type.IsValueType) return UnboxBooleanDispatcher;
  1453. return ToBoolTrue;
  1454. }
  1455. #endregion
  1456. #region conversion proxy helpers
  1457. internal static MethodInfo FindImplicitConversionOperator(Type from, Type to)
  1458. {
  1459. const BindingFlags ConversionOperatorFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy;
  1460. MethodInfo found = FindImplicitConversionMethod(from.GetMethods(ConversionOperatorFlags), from, to);
  1461. if (null != found) return found;
  1462. found = FindImplicitConversionMethod(to

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