PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/boo/boo-lang
C# | 1801 lines | 1518 code | 211 blank | 72 comment | 264 complexity | 956b3d433a531e78a4a43fe8749f3658 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)'E' << 8) + (int)'r': // op_ExclusiveOr
  372. return op_ExclusiveOr(lhs, lhsTypeCode, rhs, rhsTypeCode);
  373. case ((int)'S' << 8) + (int)'t': // op_ShiftLeft/Right
  374. return operatorName[8] == 'L' ?
  375. op_ShiftLeft(lhs, lhsTypeCode, rhs, rhsTypeCode) :
  376. op_ShiftRight(lhs, lhsTypeCode, rhs, rhsTypeCode);
  377. case ((int)'M' << 8) + (int)'h': // op_Match
  378. case ((int)'N' << 8) + (int)'h': // op_NotMatch
  379. case ((int)'M' << 8) + (int)'r': // op_Member
  380. case ((int)'N' << 8) + (int)'r': // op_NotMember
  381. default:
  382. throw new ArgumentException(lhs + " " + operatorName + " " + rhs);
  383. }
  384. }
  385. else
  386. {
  387. object[] args = new object[] { lhs, rhs };
  388. IQuackFu duck = lhs as IQuackFu;
  389. if (null != duck)
  390. {
  391. return duck.QuackInvoke(operatorName, args);
  392. }
  393. else
  394. {
  395. duck = rhs as IQuackFu;
  396. if (null != duck)
  397. {
  398. return duck.QuackInvoke(operatorName, args);
  399. }
  400. }
  401. try
  402. {
  403. // TODO: first resolve the right method on either
  404. // lhs and rhs
  405. // and then cache the final information
  406. return Invoke(lhsType, operatorName, args);
  407. }
  408. catch (MissingMethodException)
  409. {
  410. try
  411. {
  412. return Invoke(rhsType, operatorName, args);
  413. }
  414. catch (MissingMethodException)
  415. {
  416. try
  417. {
  418. return InvokeRuntimeServicesOperator(operatorName, args);
  419. }
  420. catch (MissingMethodException)
  421. {
  422. }
  423. }
  424. throw; // always throw the original exception
  425. }
  426. }
  427. }
  428. public static object InvokeUnaryOperator(string operatorName, object operand)
  429. {
  430. Type operandType = operand.GetType();
  431. TypeCode operandTypeCode = Type.GetTypeCode(operandType);
  432. if (IsNumeric(operandTypeCode))
  433. {
  434. // HACK: optimization to get to the correct operators faster
  435. // is it worthy?
  436. switch (((int)operatorName[3] << 8) + (int)operatorName[operatorName.Length - 1])
  437. {
  438. case ((int)'U' << 8) + (int)'n': // op_UnaryNegation
  439. return op_UnaryNegation(operand, operandTypeCode);
  440. default:
  441. throw new ArgumentException(operatorName + " " + operand);
  442. }
  443. }
  444. else
  445. {
  446. object[] args = new object[] { operand };
  447. IQuackFu duck = operand as IQuackFu;
  448. if (null != duck)
  449. {
  450. return duck.QuackInvoke(operatorName, args);
  451. }
  452. try
  453. {
  454. return Invoke(operandType, operatorName, args);
  455. }
  456. catch (MissingMethodException)
  457. {
  458. try
  459. {
  460. return InvokeRuntimeServicesOperator(operatorName, args);
  461. }
  462. catch (MissingMethodException)
  463. {
  464. }
  465. throw; // always throw the original exception
  466. }
  467. }
  468. }
  469. private static object InvokeRuntimeServicesOperator(string operatorName, object[] args)
  470. {
  471. return Invoke(RuntimeServicesType, operatorName, args);
  472. }
  473. public static object MoveNext(IEnumerator enumerator)
  474. {
  475. if (null == enumerator) Error("CantUnpackNull");
  476. if (!enumerator.MoveNext()) Error("UnpackListOfWrongSize");
  477. return enumerator.Current;
  478. }
  479. public static int Len(object obj)
  480. {
  481. if (null != obj)
  482. {
  483. ICollection collection = obj as ICollection;
  484. if (null != collection) return collection.Count;
  485. string s = obj as string;
  486. if (null != s) return s.Length;
  487. }
  488. throw new ArgumentException();
  489. }
  490. public static string Mid(string s, int begin, int end)
  491. {
  492. begin = NormalizeStringIndex(s, begin);
  493. end = NormalizeStringIndex(s, end);
  494. return s.Substring(begin, end - begin);
  495. }
  496. public static Array GetRange1(Array source, int begin)
  497. {
  498. return GetRange2(source, begin, source.Length);
  499. }
  500. public static Array GetRange2(Array source, int begin, int end)
  501. {
  502. int sourceLen = source.Length;
  503. begin = NormalizeIndex(sourceLen, begin);
  504. end = NormalizeIndex(sourceLen, end);
  505. int targetLen = Math.Max(0, end - begin);
  506. Array target = Array.CreateInstance(source.GetType().GetElementType(), targetLen);
  507. Array.Copy(source, begin, target, 0, targetLen);
  508. return target;
  509. }
  510. public static void SetMultiDimensionalRange1(Array source, Array dest, int[] ranges, bool[] collapse)
  511. {
  512. if (dest.Rank != ranges.Length / 2)
  513. {
  514. throw new Exception("invalid range passed: " + ranges.Length / 2 + ", expected " + dest.Rank * 2);
  515. }
  516. for (int i = 0; i < dest.Rank; i++)
  517. {
  518. if (ranges[2 * i] > 0 ||
  519. ranges[2 * i] > dest.GetLength(i) ||
  520. ranges[2 * i + 1] > dest.GetLength(i) ||
  521. ranges[2 * i + 1] < ranges[2 * i])
  522. {
  523. // FIXME: Better error reporting
  524. Error("InvalidArray");
  525. }
  526. }
  527. int sourceRank = 0;
  528. foreach (bool val in collapse)
  529. {
  530. if (!val)
  531. {
  532. sourceRank++;
  533. }
  534. }
  535. if (source.Rank != sourceRank)
  536. {
  537. // FIXME: Better error reporting
  538. Error("InvalidArray");
  539. }
  540. int[] lensDest = new int[dest.Rank];
  541. int[] lensSrc = new int[sourceRank];
  542. int rankIndex = 0;
  543. for (int i = 0; i < dest.Rank; i++)
  544. {
  545. lensDest[i] = ranges[2 * i + 1] - ranges[2 * i];
  546. if (!collapse[i])
  547. {
  548. lensSrc[rankIndex] = lensDest[i] - ranges[2 * i];
  549. if (lensSrc[rankIndex] != source.GetLength(rankIndex))
  550. {
  551. // FIXME: Better error reporting
  552. Error("InvalidArray");
  553. }
  554. rankIndex++;
  555. }
  556. }
  557. int[] modInd = new int[dest.Rank];
  558. for (int i = 0; i < dest.Rank; i++)
  559. {
  560. if (i == 0)
  561. {
  562. modInd[i] = source.Length / lensDest[lensDest.Length - 1];
  563. }
  564. else
  565. {
  566. modInd[i] = modInd[i - 1] / lensDest[i - 1];
  567. }
  568. }
  569. int counter;
  570. int[] indexDest = new int[dest.Rank];
  571. int[] indexSrc = new int[sourceRank];
  572. for (int i = 0; i < source.Length; i++)
  573. {
  574. counter = 0;
  575. for (int j = 0; j < dest.Rank; j++)
  576. {
  577. int index = (i % modInd[j]) / (modInd[j] / lensDest[j]);
  578. indexDest[j] = index;
  579. if (!collapse[j])
  580. {
  581. indexSrc[counter] = indexDest[j] + ranges[2 * j];
  582. counter++;
  583. }
  584. dest.SetValue(source.GetValue(indexSrc), indexDest);
  585. }
  586. }
  587. }
  588. public static Array GetMultiDimensionalRange1(Array source, int[] ranges, bool[] collapse)
  589. {
  590. int rankSrc = source.Rank;
  591. int collapseSize = 0;
  592. foreach (bool val in collapse)
  593. {
  594. if (val)
  595. {
  596. collapseSize++;
  597. }
  598. }
  599. int rankDest = rankSrc - collapseSize;
  600. int[] lensDest = new int[rankDest];
  601. int[] lensSrc = new int[rankSrc];
  602. int rankIndex = 0;
  603. for (int i = 0; i < rankSrc; i++)
  604. {
  605. ranges[2 * i] = NormalizeIndex(source.GetLength(i), ranges[2 * i]);
  606. ranges[2 * i + 1] = NormalizeIndex(source.GetLength(i), ranges[2 * i + 1]);
  607. lensSrc[i] = ranges[2 * i + 1] - ranges[2 * i];
  608. if (!collapse[i])
  609. {
  610. lensDest[rankIndex] = ranges[2 * i + 1] - ranges[2 * i];
  611. rankIndex++;
  612. }
  613. }
  614. Array dest = Array.CreateInstance(source.GetType().GetElementType(), lensDest);
  615. int[] modInd = new int[rankSrc];
  616. int[] indicesDest = new int[rankDest];
  617. int[] indicesSrc = new int[rankSrc];
  618. for (int i = 0; i < rankSrc; i++)
  619. {
  620. if (i == 0)
  621. {
  622. modInd[i] = dest.Length;
  623. }
  624. else
  625. {
  626. modInd[i] = modInd[i - 1] / lensSrc[i - 1];
  627. }
  628. }
  629. for (int i = 0; i < dest.Length; i++)
  630. {
  631. int destIndex = 0;
  632. for (int j = 0; j < rankSrc; j++)
  633. {
  634. int index = (i % modInd[j]) / (modInd[j] / lensSrc[j]);
  635. indicesSrc[j] = ranges[2 * j] + index;
  636. if (!collapse[j])
  637. {
  638. indicesDest[destIndex] = indicesSrc[j] - ranges[2 * j];
  639. destIndex++;
  640. }
  641. }
  642. dest.SetValue(source.GetValue(indicesSrc), indicesDest);
  643. }
  644. return dest;
  645. }
  646. public static void CheckArrayUnpack(Array array, int expected)
  647. {
  648. if (null == array)
  649. {
  650. Error("CantUnpackNull");
  651. }
  652. if (expected > array.Length)
  653. {
  654. Error("UnpackArrayOfWrongSize", expected, array.Length);
  655. }
  656. }
  657. public static int NormalizeIndex(int len, int index)
  658. {
  659. if (index < 0)
  660. {
  661. index += len;
  662. if (index < 0) return 0;
  663. }
  664. if (index > len) return len;
  665. return index;
  666. }
  667. public static int NormalizeArrayIndex(Array array, int index)
  668. {
  669. return NormalizeIndex(array.Length, index);
  670. }
  671. public static int NormalizeStringIndex(string s, int index)
  672. {
  673. return NormalizeIndex(s.Length, index);
  674. }
  675. public static IEnumerable GetEnumerable(object enumerable)
  676. {
  677. if (null == enumerable) Error("CantEnumerateNull");
  678. IEnumerable iterator = enumerable as IEnumerable;
  679. if (null != iterator) return iterator;
  680. TextReader reader = enumerable as TextReader;
  681. if (null != reader) return TextReaderEnumerator.lines(reader);
  682. Error("ArgumentNotEnumerable");
  683. return null;
  684. }
  685. #region global operators
  686. public static Array AddArrays(Type resultingElementType, Array lhs, Array rhs)
  687. {
  688. int resultingLen = lhs.Length + rhs.Length;
  689. Array result = Array.CreateInstance(resultingElementType, resultingLen);
  690. Array.Copy(lhs, 0, result, 0, lhs.Length);
  691. Array.Copy(rhs, 0, result, lhs.Length, rhs.Length);
  692. return result;
  693. }
  694. public static string op_Addition(string lhs, string rhs)
  695. {
  696. return string.Concat(lhs, rhs);
  697. }
  698. public static string op_Addition(string lhs, object rhs)
  699. {
  700. return string.Concat(lhs, rhs);
  701. }
  702. public static string op_Addition(object lhs, string rhs)
  703. {
  704. return string.Concat(lhs, rhs);
  705. }
  706. public static Array op_Multiply(Array lhs, int count)
  707. {
  708. if (count < 0)
  709. {
  710. throw new ArgumentOutOfRangeException("count");
  711. }
  712. Type type = lhs.GetType();
  713. if (1 != type.GetArrayRank())
  714. {
  715. throw new ArgumentException("lhs");
  716. }
  717. int length = lhs.Length;
  718. Array result = Array.CreateInstance(type.GetElementType(), length * count);
  719. int destinationIndex = 0;
  720. for (int i = 0; i < count; ++i)
  721. {
  722. Array.Copy(lhs, 0, result, destinationIndex, length);
  723. destinationIndex += length;
  724. }
  725. return result;
  726. }
  727. public static Array op_Multiply(int count, Array rhs)
  728. {
  729. return op_Multiply(rhs, count);
  730. }
  731. public static string op_Multiply(string lhs, int count)
  732. {
  733. if (count < 0)
  734. {
  735. throw new ArgumentOutOfRangeException("count");
  736. }
  737. string result = null;
  738. if (null != lhs)
  739. {
  740. StringBuilder builder = new StringBuilder(lhs.Length * count);
  741. for (int i = 0; i < count; ++i)
  742. {
  743. builder.Append(lhs);
  744. }
  745. result = builder.ToString();
  746. }
  747. return result;
  748. }
  749. public static string op_Multiply(int count, string rhs)
  750. {
  751. return op_Multiply(rhs, count);
  752. }
  753. public static bool op_NotMember(string lhs, string rhs)
  754. {
  755. return !op_Member(lhs, rhs);
  756. }
  757. public static bool op_Member(string lhs, string rhs)
  758. {
  759. if (null == lhs || null == rhs)
  760. {
  761. return false;
  762. }
  763. return rhs.IndexOf(lhs) > -1;
  764. }
  765. #if !NO_SYSTEM_DLL
  766. public static bool op_Match(string input, System.Text.RegularExpressions.Regex pattern)
  767. {
  768. return pattern.IsMatch(input);
  769. }
  770. public static bool op_Match(string input, string pattern)
  771. {
  772. return System.Text.RegularExpressions.Regex.IsMatch(input, pattern);
  773. }
  774. public static bool op_NotMatch(string input, System.Text.RegularExpressions.Regex pattern)
  775. {
  776. return !op_Match(input, pattern);
  777. }
  778. public static bool op_NotMatch(string input, string pattern)
  779. {
  780. return !op_Match(input, pattern);
  781. }
  782. #endif
  783. public static string op_Modulus(string lhs, IEnumerable rhs)
  784. {
  785. return string.Format(lhs, Boo.Lang.Builtins.array(rhs));
  786. }
  787. public static string op_Modulus(string lhs, object[] rhs)
  788. {
  789. return string.Format(lhs, rhs);
  790. }
  791. public static bool op_Member(object lhs, IList rhs)
  792. {
  793. if (null == rhs)
  794. {
  795. return false;
  796. }
  797. return rhs.Contains(lhs);
  798. }
  799. public static bool op_NotMember(object lhs, IList rhs)
  800. {
  801. return !op_Member(lhs, rhs);
  802. }
  803. public static bool op_Member(object lhs, IDictionary rhs)
  804. {
  805. if (null == rhs)
  806. {
  807. return false;
  808. }
  809. return rhs.Contains(lhs);
  810. }
  811. public static bool op_NotMember(object lhs, IDictionary rhs)
  812. {
  813. return !op_Member(lhs, rhs);
  814. }
  815. public static bool op_Member(object lhs, IEnumerable rhs)
  816. {
  817. if (null == rhs)
  818. {
  819. return false;
  820. }
  821. foreach (object item in rhs)
  822. {
  823. if (EqualityOperator(lhs, item))
  824. {
  825. return true;
  826. }
  827. }
  828. return false;
  829. }
  830. public static bool op_NotMember(object lhs, IEnumerable rhs)
  831. {
  832. return !op_Member(lhs, rhs);
  833. }
  834. public static bool EqualityOperator(object lhs, object rhs)
  835. {
  836. if (lhs == rhs) return true;
  837. // Some types do overload Equals to compare
  838. // against null values
  839. if (null == lhs) return rhs.Equals(lhs);
  840. if (null == rhs) return lhs.Equals(rhs);
  841. TypeCode lhsTypeCode = Type.GetTypeCode(lhs.GetType());
  842. TypeCode rhsTypeCode = Type.GetTypeCode(rhs.GetType());
  843. if (IsNumeric(lhsTypeCode) && IsNumeric(rhsTypeCode))
  844. {
  845. return EqualityOperator(lhs, lhsTypeCode, rhs, rhsTypeCode);
  846. }
  847. Array lhsa = lhs as Array;
  848. if (null != lhsa)
  849. {
  850. Array rhsa = rhs as Array;
  851. if (null != rhsa)
  852. {
  853. return ArrayEqualityImpl(lhsa, rhsa);
  854. }
  855. }
  856. return lhs.Equals(rhs) || rhs.Equals(lhs);
  857. }
  858. public static bool op_Equality(Array lhs, Array rhs)
  859. {
  860. if (lhs == rhs)
  861. {
  862. return true;
  863. }
  864. if (null == lhs || null == rhs)
  865. {
  866. return false;
  867. }
  868. return ArrayEqualityImpl(lhs, rhs);
  869. }
  870. static bool ArrayEqualityImpl(Array lhs, Array rhs)
  871. {
  872. if (1 != lhs.Rank || 1 != rhs.Rank)
  873. {
  874. throw new ArgumentException("array rank must be 1");
  875. }
  876. if (lhs.Length != rhs.Length)
  877. {
  878. return false;
  879. }
  880. for (int i = 0; i < lhs.Length; ++i)
  881. {
  882. if (!EqualityOperator(lhs.GetValue(i), rhs.GetValue(i)))
  883. {
  884. return false;
  885. }
  886. }
  887. return true;
  888. }
  889. #endregion
  890. #region dynamic operator for primitive types
  891. private static TypeCode GetConvertTypeCode(TypeCode lhsTypeCode, TypeCode rhsTypeCode)
  892. {
  893. /* C# ECMA Spec V2
  894. * 14.2.6.2 Binary numeric promotions
  895. * This clause is informative.
  896. * Binary numeric promotion occurs for the operands of the predefined +, ?, *, /, %, &, |, ^, ==, !=, >, <, >=,
  897. * and <= binary operators. Binary numeric promotion implicitly converts both operands to a common type
  898. * which, in case of the non-relational operators, also becomes the result type of the operation. Binary numeric
  899. * promotion consists of applying the following rules, in the order they appear here:
  900. * � If either operand is of type decimal, the other operand is converted to type decimal, or a compiletime
  901. * error occurs if the other operand is of type float or double.
  902. * � Otherwise, if either operand is of type double, the other operand is converted to type double.
  903. * � Otherwise, if either operand is of type float, the other operand is converted to type float.
  904. * � Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a
  905. * compile-time error occurs if the other operand is of type sbyte, short, int, or long.
  906. * � Otherwise, if either operand is of type long, the other operand is converted to type long.
  907. * � Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int,
  908. * both operands are converted to type long.
  909. * � Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  910. * � Otherwise, both operands are converted to type int.
  911. * [Note: The first rule disallows any operations that mix the decimal type with the double and float types.
  912. * The rule follows from the fact that there are no implicit conversions between the decimal type and the
  913. * double and float types. end note]
  914. * [Note: Also note that it is not possible for an operand to be of type ulong when the other operand is of a
  915. * signed integral type. The reason is that no integral type exists that can represent the full range of ulong as
  916. * well as the signed integral types. end note]
  917. * In both of the above cases, a cast expression can be used to explicitly convert one operand to a type that is
  918. * compatible with the other operand.
  919. */
  920. if (TypeCode.Decimal == lhsTypeCode || TypeCode.Decimal == rhsTypeCode)
  921. {
  922. return TypeCode.Decimal; // not per ECMA spec
  923. }
  924. if (TypeCode.Double == lhsTypeCode || TypeCode.Double == rhsTypeCode)
  925. {
  926. return TypeCode.Double;
  927. }
  928. if (TypeCode.Single == lhsTypeCode || TypeCode.Single == rhsTypeCode)
  929. {
  930. return TypeCode.Single;
  931. }
  932. if (TypeCode.UInt64 == lhsTypeCode)
  933. {
  934. if (TypeCode.SByte == rhsTypeCode || TypeCode.Int16 == rhsTypeCode ||
  935. TypeCode.Int32 == rhsTypeCode || TypeCode.Int64 == rhsTypeCode)
  936. {
  937. // throw new ArgumentException("ulong <op> " + rhsTypeCode);
  938. return TypeCode.Int64; // not per Ecma spec
  939. }
  940. return TypeCode.UInt64;
  941. }
  942. if (TypeCode.UInt64 == rhsTypeCode)
  943. {
  944. if (TypeCode.SByte == lhsTypeCode || TypeCode.Int16 == lhsTypeCode ||
  945. TypeCode.Int32 == lhsTypeCode || TypeCode.Int64 == lhsTypeCode)
  946. {
  947. // throw new ArgumentException(lhsTypeCode + " <op> ulong");
  948. return TypeCode.Int64; // not per Ecma spec
  949. }
  950. return TypeCode.UInt64;
  951. }
  952. if (TypeCode.Int64 == lhsTypeCode || TypeCode.Int64 == rhsTypeCode)
  953. {
  954. return TypeCode.Int64;
  955. }
  956. if (TypeCode.UInt32 == lhsTypeCode)
  957. {
  958. if (TypeCode.SByte == rhsTypeCode || TypeCode.Int16 == rhsTypeCode ||
  959. TypeCode.Int32 == rhsTypeCode)
  960. {
  961. return TypeCode.Int64;
  962. }
  963. return TypeCode.UInt32;
  964. }
  965. if (TypeCode.UInt32 == rhsTypeCode)
  966. {
  967. if (TypeCode.SByte == lhsTypeCode || TypeCode.Int16 == lhsTypeCode ||
  968. TypeCode.Int32 == lhsTypeCode)
  969. {
  970. return TypeCode.Int64;
  971. }
  972. return TypeCode.UInt32;
  973. }
  974. return TypeCode.Int32;
  975. }
  976. private static object op_Multiply(object lhs, TypeCode lhsTypeCode,
  977. object rhs, TypeCode rhsTypeCode)
  978. {
  979. IConvertible lhsConvertible = (IConvertible)lhs;
  980. IConvertible rhsConvertible = (IConvertible)rhs;
  981. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  982. {
  983. case TypeCode.Decimal:
  984. return lhsConvertible.ToDecimal(null) * rhsConvertible.ToDecimal(null);
  985. case TypeCode.Double:
  986. return lhsConvertible.ToDouble(null) * rhsConvertible.ToDouble(null);
  987. case TypeCode.Single:
  988. return lhsConvertible.ToSingle(null) * rhsConvertible.ToSingle(null);
  989. case TypeCode.UInt64:
  990. return lhsConvertible.ToUInt64(null) * rhsConvertible.ToUInt64(null);
  991. case TypeCode.Int64:
  992. return lhsConvertible.ToInt64(null) * rhsConvertible.ToInt64(null);
  993. case TypeCode.UInt32:
  994. return lhsConvertible.ToUInt32(null) * rhsConvertible.ToUInt32(null);
  995. case TypeCode.Int32:
  996. default:
  997. return lhsConvertible.ToInt32(null) * rhsConvertible.ToInt32(null);
  998. }
  999. }
  1000. private static object op_Division(object lhs, TypeCode lhsTypeCode,
  1001. object rhs, TypeCode rhsTypeCode)
  1002. {
  1003. IConvertible lhsConvertible = (IConvertible)lhs;
  1004. IConvertible rhsConvertible = (IConvertible)rhs;
  1005. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1006. {
  1007. case TypeCode.Decimal:
  1008. return lhsConvertible.ToDecimal(null) / rhsConvertible.ToDecimal(null);
  1009. case TypeCode.Double:
  1010. return lhsConvertible.ToDouble(null) / rhsConvertible.ToDouble(null);
  1011. case TypeCode.Single:
  1012. return lhsConvertible.ToSingle(null) / rhsConvertible.ToSingle(null);
  1013. case TypeCode.UInt64:
  1014. return lhsConvertible.ToUInt64(null) / rhsConvertible.ToUInt64(null);
  1015. case TypeCode.Int64:
  1016. return lhsConvertible.ToInt64(null) / rhsConvertible.ToInt64(null);
  1017. case TypeCode.UInt32:
  1018. return lhsConvertible.ToUInt32(null) / rhsConvertible.ToUInt32(null);
  1019. case TypeCode.Int32:
  1020. default:
  1021. return lhsConvertible.ToInt32(null) / rhsConvertible.ToInt32(null);
  1022. }
  1023. }
  1024. private static object op_Addition(object lhs, TypeCode lhsTypeCode,
  1025. object rhs, TypeCode rhsTypeCode)
  1026. {
  1027. IConvertible lhsConvertible = (IConvertible)lhs;
  1028. IConvertible rhsConvertible = (IConvertible)rhs;
  1029. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1030. {
  1031. case TypeCode.Decimal:
  1032. return lhsConvertible.ToDecimal(null) + rhsConvertible.ToDecimal(null);
  1033. case TypeCode.Double:
  1034. return lhsConvertible.ToDouble(null) + rhsConvertible.ToDouble(null);
  1035. case TypeCode.Single:
  1036. return lhsConvertible.ToSingle(null) + rhsConvertible.ToSingle(null);
  1037. case TypeCode.UInt64:
  1038. return lhsConvertible.ToUInt64(null) + rhsConvertible.ToUInt64(null);
  1039. case TypeCode.Int64:
  1040. return lhsConvertible.ToInt64(null) + rhsConvertible.ToInt64(null);
  1041. case TypeCode.UInt32:
  1042. return lhsConvertible.ToUInt32(null) + rhsConvertible.ToUInt32(null);
  1043. case TypeCode.Int32:
  1044. default:
  1045. return lhsConvertible.ToInt32(null) + rhsConvertible.ToInt32(null);
  1046. }
  1047. }
  1048. private static object op_Subtraction(object lhs, TypeCode lhsTypeCode,
  1049. object rhs, TypeCode rhsTypeCode)
  1050. {
  1051. IConvertible lhsConvertible = (IConvertible)lhs;
  1052. IConvertible rhsConvertible = (IConvertible)rhs;
  1053. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1054. {
  1055. case TypeCode.Decimal:
  1056. return lhsConvertible.ToDecimal(null) - rhsConvertible.ToDecimal(null);
  1057. case TypeCode.Double:
  1058. return lhsConvertible.ToDouble(null) - rhsConvertible.ToDouble(null);
  1059. case TypeCode.Single:
  1060. return lhsConvertible.ToSingle(null) - rhsConvertible.ToSingle(null);
  1061. case TypeCode.UInt64:
  1062. return lhsConvertible.ToUInt64(null) - rhsConvertible.ToUInt64(null);
  1063. case TypeCode.Int64:
  1064. return lhsConvertible.ToInt64(null) - rhsConvertible.ToInt64(null);
  1065. case TypeCode.UInt32:
  1066. return lhsConvertible.ToUInt32(null) - rhsConvertible.ToUInt32(null);
  1067. case TypeCode.Int32:
  1068. default:
  1069. return lhsConvertible.ToInt32(null) - rhsConvertible.ToInt32(null);
  1070. }
  1071. }
  1072. private static bool EqualityOperator(object lhs, TypeCode lhsTypeCode,
  1073. object rhs, TypeCode rhsTypeCode)
  1074. {
  1075. IConvertible lhsConvertible = (IConvertible)lhs;
  1076. IConvertible rhsConvertible = (IConvertible)rhs;
  1077. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1078. {
  1079. case TypeCode.Decimal:
  1080. return lhsConvertible.ToDecimal(null) == rhsConvertible.ToDecimal(null);
  1081. case TypeCode.Double:
  1082. return lhsConvertible.ToDouble(null) == rhsConvertible.ToDouble(null);
  1083. case TypeCode.Single:
  1084. return lhsConvertible.ToSingle(null) == rhsConvertible.ToSingle(null);
  1085. case TypeCode.UInt64:
  1086. return lhsConvertible.ToUInt64(null) == rhsConvertible.ToUInt64(null);
  1087. case TypeCode.Int64:
  1088. return lhsConvertible.ToInt64(null) == rhsConvertible.ToInt64(null);
  1089. case TypeCode.UInt32:
  1090. return lhsConvertible.ToUInt32(null) == rhsConvertible.ToUInt32(null);
  1091. case TypeCode.Int32:
  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. case TypeCode.Int32:
  1116. default:
  1117. return lhsConvertible.ToInt32(null) > rhsConvertible.ToInt32(null);
  1118. }
  1119. }
  1120. private static bool op_GreaterThanOrEqual(object lhs, TypeCode lhsTypeCode,
  1121. object rhs, TypeCode rhsTypeCode)
  1122. {
  1123. IConvertible lhsConvertible = (IConvertible)lhs;
  1124. IConvertible rhsConvertible = (IConvertible)rhs;
  1125. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1126. {
  1127. case TypeCode.Decimal:
  1128. return lhsConvertible.ToDecimal(null) >= rhsConvertible.ToDecimal(null);
  1129. case TypeCode.Double:
  1130. return lhsConvertible.ToDouble(null) >= rhsConvertible.ToDouble(null);
  1131. case TypeCode.Single:
  1132. return lhsConvertible.ToSingle(null) >= rhsConvertible.ToSingle(null);
  1133. case TypeCode.UInt64:
  1134. return lhsConvertible.ToUInt64(null) >= rhsConvertible.ToUInt64(null);
  1135. case TypeCode.Int64:
  1136. return lhsConvertible.ToInt64(null) >= rhsConvertible.ToInt64(null);
  1137. case TypeCode.UInt32:
  1138. return lhsConvertible.ToUInt32(null) >= rhsConvertible.ToUInt32(null);
  1139. case TypeCode.Int32:
  1140. default:
  1141. return lhsConvertible.ToInt32(null) >= rhsConvertible.ToInt32(null);
  1142. }
  1143. }
  1144. private static bool op_LessThan(object lhs, TypeCode lhsTypeCode,
  1145. object rhs, TypeCode rhsTypeCode)
  1146. {
  1147. IConvertible lhsConvertible = (IConvertible)lhs;
  1148. IConvertible rhsConvertible = (IConvertible)rhs;
  1149. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1150. {
  1151. case TypeCode.Decimal:
  1152. return lhsConvertible.ToDecimal(null) < rhsConvertible.ToDecimal(null);
  1153. case TypeCode.Double:
  1154. return lhsConvertible.ToDouble(null) < rhsConvertible.ToDouble(null);
  1155. case TypeCode.Single:
  1156. return lhsConvertible.ToSingle(null) < rhsConvertible.ToSingle(null);
  1157. case TypeCode.UInt64:
  1158. return lhsConvertible.ToUInt64(null) < rhsConvertible.ToUInt64(null);
  1159. case TypeCode.Int64:
  1160. return lhsConvertible.ToInt64(null) < rhsConvertible.ToInt64(null);
  1161. case TypeCode.UInt32:
  1162. return lhsConvertible.ToUInt32(null) < rhsConvertible.ToUInt32(null);
  1163. case TypeCode.Int32:
  1164. default:
  1165. return lhsConvertible.ToInt32(null) < rhsConvertible.ToInt32(null);
  1166. }
  1167. }
  1168. private static bool op_LessThanOrEqual(object lhs, TypeCode lhsTypeCode,
  1169. object rhs, TypeCode rhsTypeCode)
  1170. {
  1171. IConvertible lhsConvertible = (IConvertible)lhs;
  1172. IConvertible rhsConvertible = (IConvertible)rhs;
  1173. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1174. {
  1175. case TypeCode.Decimal:
  1176. return lhsConvertible.ToDecimal(null) <= rhsConvertible.ToDecimal(null);
  1177. case TypeCode.Double:
  1178. return lhsConvertible.ToDouble(null) <= rhsConvertible.ToDouble(null);
  1179. case TypeCode.Single:
  1180. return lhsConvertible.ToSingle(null) <= rhsConvertible.ToSingle(null);
  1181. case TypeCode.UInt64:
  1182. return lhsConvertible.ToUInt64(null) <= rhsConvertible.ToUInt64(null);
  1183. case TypeCode.Int64:
  1184. return lhsConvertible.ToInt64(null) <= rhsConvertible.ToInt64(null);
  1185. case TypeCode.UInt32:
  1186. return lhsConvertible.ToUInt32(null) <= rhsConvertible.ToUInt32(null);
  1187. case TypeCode.Int32:
  1188. default:
  1189. return lhsConvertible.ToInt32(null) <= rhsConvertible.ToInt32(null);
  1190. }
  1191. }
  1192. private static object op_Modulus(object lhs, TypeCode lhsTypeCode,
  1193. object rhs, TypeCode rhsTypeCode)
  1194. {
  1195. IConvertible lhsConvertible = (IConvertible)lhs;
  1196. IConvertible rhsConvertible = (IConvertible)rhs;
  1197. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1198. {
  1199. case TypeCode.Decimal:
  1200. return lhsConvertible.ToDecimal(null) % rhsConvertible.ToDecimal(null);
  1201. case TypeCode.Double:
  1202. return lhsConvertible.ToDouble(null) % rhsConvertible.ToDouble(null);
  1203. case TypeCode.Single:
  1204. return lhsConvertible.ToSingle(null) % rhsConvertible.ToSingle(null);
  1205. case TypeCode.UInt64:
  1206. return lhsConvertible.ToUInt64(null) % rhsConvertible.ToUInt64(null);
  1207. case TypeCode.Int64:
  1208. return lhsConvertible.ToInt64(null) % rhsConvertible.ToInt64(null);
  1209. case TypeCode.UInt32:
  1210. return lhsConvertible.ToUInt32(null) % rhsConvertible.ToUInt32(null);
  1211. case TypeCode.Int32:
  1212. default:
  1213. return lhsConvertible.ToInt32(null) % rhsConvertible.ToInt32(null);
  1214. }
  1215. }
  1216. private static double op_Exponentiation(object lhs, TypeCode lhsTypeCode,
  1217. object rhs, TypeCode rhsTypeCode)
  1218. {
  1219. IConvertible lhsConvertible = (IConvertible)lhs;
  1220. IConvertible rhsConvertible = (IConvertible)rhs;
  1221. return Math.Pow(lhsConvertible.ToDouble(null), rhsConvertible.ToDouble(null));
  1222. }
  1223. private static object op_BitwiseAnd(object lhs, TypeCode lhsTypeCode,
  1224. object rhs, TypeCode rhsTypeCode)
  1225. {
  1226. IConvertible lhsConvertible = (IConvertible)lhs;
  1227. IConvertible rhsConvertible = (IConvertible)rhs;
  1228. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1229. {
  1230. case TypeCode.Decimal:
  1231. case TypeCode.Double:
  1232. case TypeCode.Single:
  1233. throw new ArgumentException(lhsTypeCode + " & " + rhsTypeCode);
  1234. case TypeCode.UInt64:
  1235. return lhsConvertible.ToUInt64(null) & rhsConvertible.ToUInt64(null);
  1236. case TypeCode.Int64:
  1237. return lhsConvertible.ToInt64(null) & rhsConvertible.ToInt64(null);
  1238. case TypeCode.UInt32:
  1239. return lhsConvertible.ToUInt32(null) & rhsConvertible.ToUInt32(null);
  1240. case TypeCode.Int32:
  1241. default:
  1242. return lhsConvertible.ToInt32(null) & rhsConvertible.ToInt32(null);
  1243. }
  1244. }
  1245. private static object op_BitwiseOr(object lhs, TypeCode lhsTypeCode,
  1246. object rhs, TypeCode rhsTypeCode)
  1247. {
  1248. IConvertible lhsConvertible = (IConvertible)lhs;
  1249. IConvertible rhsConvertible = (IConvertible)rhs;
  1250. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1251. {
  1252. case TypeCode.Decimal:
  1253. case TypeCode.Double:
  1254. case TypeCode.Single:
  1255. throw new ArgumentException(lhsTypeCode + " | " + rhsTypeCode);
  1256. case TypeCode.UInt64:
  1257. return lhsConvertible.ToUInt64(null) | rhsConvertible.ToUInt64(null);
  1258. case TypeCode.Int64:
  1259. return lhsConvertible.ToInt64(null) | rhsConvertible.ToInt64(null);
  1260. case TypeCode.UInt32:
  1261. return lhsConvertible.ToUInt32(null) | rhsConvertible.ToUInt32(null);
  1262. case TypeCode.Int32:
  1263. default:
  1264. return lhsConvertible.ToInt32(null) | rhsConvertible.ToInt32(null);
  1265. }
  1266. }
  1267. private static object op_ExclusiveOr(object lhs, TypeCode lhsTypeCode,
  1268. object rhs, TypeCode rhsTypeCode)
  1269. {
  1270. IConvertible lhsConvertible = (IConvertible)lhs;
  1271. IConvertible rhsConvertible = (IConvertible)rhs;
  1272. switch (GetConvertTypeCode(lhsTypeCode, rhsTypeCode))
  1273. {
  1274. case TypeCode.Decimal:
  1275. case TypeCode.Double:
  1276. case TypeCode.Single:
  1277. throw new ArgumentException(lhsTypeCode + " ^ " + rhsTypeCode);
  1278. case TypeCode.UInt64:
  1279. return lhsConvertible.ToUInt64(null) ^ rhsConvertible.ToUInt64(null);
  1280. case TypeCode.Int64:
  1281. return lhsConvertible.ToInt64(null) ^ rhsConvertible.ToInt64(null);
  1282. case TypeCode.UInt32:
  1283. return lhsConvertible.ToUInt32(null) ^ rhsConvertible.ToUInt32(null);
  1284. case TypeCode.Int32:
  1285. default:
  1286. return lhsConvertible.ToInt32(null) ^ rhsConvertible.ToInt32(null);
  1287. }
  1288. }
  1289. private static object op_ShiftLeft(object lhs, TypeCode lhsTypeCode,
  1290. object rhs, TypeCode rhsTypeCode)
  1291. {
  1292. IConvertible lhsConvertible = (IConvertible)lhs;
  1293. IConvertible rhsConvertible = (IConvertible)rhs;
  1294. switch(rhsTypeCode)
  1295. {
  1296. case TypeCode.Decimal:
  1297. case TypeCode.Double:
  1298. case TypeCode.Single:
  1299. throw new ArgumentException(lhsTypeCode + " << " + rhsTypeCode);
  1300. default:
  1301. break;
  1302. }
  1303. switch (lhsTypeCode)
  1304. {
  1305. case TypeCode.Decimal:
  1306. case TypeCode.Double:
  1307. case TypeCode.Single:
  1308. throw new ArgumentException(lhsTypeCode + " << " + rhsTypeCode);
  1309. case TypeCode.UInt64:
  1310. return lhsConvertible.ToUInt64(null) << rhsConvertible.ToInt32(null);
  1311. case TypeCode.Int64:
  1312. return lhsConvertible.ToInt64(null) << rhsConvertible.ToInt32(null);
  1313. case TypeCode.UInt32:
  1314. return lhsConvertible.ToUInt32(null) << rhsConvertible.ToInt32(null);
  1315. case TypeCode.Int32:
  1316. default:
  1317. return lhsConvertible.ToInt32(null) << rhsConvertible.ToInt32(null);
  1318. }
  1319. }
  1320. private static object op_ShiftRight(object lhs, TypeCode lhsTypeCode,
  1321. object rhs, TypeCode rhsTypeCode)
  1322. {
  1323. IConvertible lhsConvertible = (IConvertible)lhs;
  1324. IConvertible rhsConvertible = (IConvertible)rhs;
  1325. switch(rhsTypeCode)
  1326. {
  1327. case TypeCode.Decimal:
  1328. case TypeCode.Double:
  1329. case TypeCode.Single:
  1330. throw new ArgumentException(lhsTypeCode + " >> " + rhsTypeCode);
  1331. default:
  1332. break;
  1333. }
  1334. switch (lhsTypeCode)
  1335. {
  1336. case TypeCode.Decimal:
  1337. case TypeCode.Double:
  1338. case TypeCode.Single:
  1339. throw new ArgumentException(lhsTypeCode + " >> " + rhsTypeCode);
  1340. case TypeCode.UInt64:
  1341. return lhsConvertible.ToUInt64(null) >> rhsConvertible.ToInt32(null);
  1342. case TypeCode.Int64:
  1343. return lhsConvertible.ToInt64(null) >> rhsConvertible.ToInt32(null);
  1344. case TypeCode.UInt32:
  1345. return lhsConvertible.ToUInt32(null) >> rhsConvertible.ToInt32(null);
  1346. case TypeCode.Int32:
  1347. default:
  1348. return lhsConvertible.ToInt32(null) >> rhsConvertible.ToInt32(null);
  1349. }
  1350. }
  1351. private static object op_UnaryNegation(object operand, TypeCode operandTypeCode)
  1352. {
  1353. IConvertible operandConvertible = (IConvertible)operand;
  1354. switch (operandTypeCode)
  1355. {
  1356. case TypeCode.Decimal:
  1357. return -operandConvertible.ToDecimal(null);
  1358. case TypeCode.Double:
  1359. return -operandConvertible.ToDouble(null);
  1360. case TypeCode.Single:
  1361. return -operandConvertible.ToSingle(null);
  1362. case TypeCode.UInt64:
  1363. return -operandConvertible.ToInt64(null);
  1364. case TypeCode.Int64:
  1365. return -operandConvertible.To

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