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

/DICK.B1/IronPython/Runtime/Operations/InstanceOps.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 962 lines | 664 code | 187 blank | 111 comment | 154 complexity | 123a51a2d604f3a0e96600dc136d01c8 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. #if !CLR2
  16. using System.Linq.Expressions;
  17. #else
  18. using Microsoft.Scripting.Ast;
  19. #endif
  20. using System;
  21. using System.Collections;
  22. using System.Collections.Generic;
  23. using System.Diagnostics;
  24. using System.Dynamic;
  25. using System.Reflection;
  26. using System.Runtime.CompilerServices;
  27. using Microsoft.Scripting;
  28. using Microsoft.Scripting.Runtime;
  29. using Microsoft.Scripting.Utils;
  30. using IronPython.Runtime.Exceptions;
  31. using IronPython.Runtime.Types;
  32. namespace IronPython.Runtime.Operations {
  33. /// <summary>
  34. /// InstanceOps contains methods that get added to CLS types depending on what
  35. /// methods and constructors they define. These have not been added directly to
  36. /// PythonType since they need to be added conditionally.
  37. ///
  38. /// Possibilities include:
  39. ///
  40. /// __new__, one of 3 __new__ sets can be added:
  41. /// DefaultNew - This is the __new__ used for a PythonType (list, dict, object, etc...) that
  42. /// has only 1 default public constructor that takes no parameters. These types are
  43. /// mutable types, and __new__ returns a new instance of the type, and __init__ can be used
  44. /// to re-initialize the types. This __new__ allows an unlimited number of arguments to
  45. /// be passed if a non-default __init__ is also defined.
  46. ///
  47. /// NonDefaultNew - This is used when a type has more than one constructor, or only has one
  48. /// that takes more than zero parameters. This __new__ does not allow an arbitrary # of
  49. /// extra arguments.
  50. ///
  51. /// DefaultNewCls - This is the default new used for CLS types that have only a single ctor
  52. /// w/ an arbitray number of arguments. This constructor allows setting of properties
  53. /// based upon an extra set of kw-args, e.g.: System.Windows.Forms.Button(Text='abc'). It
  54. /// is only used on non-Python types.
  55. ///
  56. /// __init__:
  57. /// For types that do not define __init__ we have an __init__ function that takes an
  58. /// unlimited number of arguments and does nothing. All types share the same reference
  59. /// to 1 instance of this.
  60. ///
  61. /// next: Defined when a type is an enumerator to expose the Python iter protocol.
  62. ///
  63. ///
  64. /// repr: Added for types that override ToString
  65. ///
  66. /// get: added for types that implement IDescriptor
  67. /// </summary>
  68. public static class InstanceOps {
  69. #region Construction
  70. [MultiRuntimeAware]
  71. private static BuiltinFunction _New;
  72. internal static readonly BuiltinFunction NewCls = CreateFunction("__new__", "DefaultNew", "DefaultNewClsKW");
  73. internal static readonly BuiltinFunction OverloadedNew = CreateFunction("__new__", "OverloadedNewBasic", "OverloadedNewKW", "OverloadedNewClsKW");
  74. internal static readonly BuiltinFunction NonDefaultNewInst = CreateNonDefaultNew();
  75. [MultiRuntimeAware]
  76. internal static BuiltinMethodDescriptor _Init;
  77. internal static BuiltinMethodDescriptor Init {
  78. get {
  79. if (_Init == null) {
  80. _Init = GetInitMethod();
  81. }
  82. return _Init;
  83. }
  84. }
  85. internal static BuiltinFunction New {
  86. get {
  87. if (_New == null) {
  88. _New = (BuiltinFunction)PythonTypeOps.GetSlot(
  89. TypeInfo.GetExtensionMemberGroup(typeof(object), typeof(ObjectOps).GetMember("__new__")),
  90. "__new__",
  91. false // privateBinding
  92. );
  93. }
  94. return _New;
  95. }
  96. }
  97. internal static BuiltinFunction CreateNonDefaultNew() {
  98. return CreateFunction("__new__", "NonDefaultNew", "NonDefaultNewKW", "NonDefaultNewKWNoParams");
  99. }
  100. public static object DefaultNew(CodeContext context, PythonType type\u00F8, params object[] args\u00F8) {
  101. if (type\u00F8 == null) throw PythonOps.TypeError("__new__ expected type object, got {0}", PythonOps.Repr(context, DynamicHelpers.GetPythonType(type\u00F8)));
  102. CheckNewArgs(context, null, args\u00F8, type\u00F8);
  103. return type\u00F8.CreateInstance(context);
  104. }
  105. public static object DefaultNewClsKW(CodeContext context, PythonType type\u00F8, [ParamDictionary]IDictionary<object, object> kwargs\u00F8, params object[] args\u00F8) {
  106. object res = DefaultNew(context, type\u00F8, args\u00F8);
  107. if (kwargs\u00F8.Count > 0) {
  108. foreach (KeyValuePair<object, object> kvp in (IDictionary<object, object>)kwargs\u00F8) {
  109. PythonOps.SetAttr(context,
  110. res,
  111. kvp.Key.ToString(),
  112. kvp.Value);
  113. }
  114. }
  115. return res;
  116. }
  117. public static object OverloadedNewBasic(CodeContext context, SiteLocalStorage<CallSite<Func<CallSite, CodeContext, object, object[], object>>> storage, BuiltinFunction overloads\u00F8, PythonType type\u00F8, params object[] args\u00F8) {
  118. if (type\u00F8 == null) throw PythonOps.TypeError("__new__ expected type object, got {0}", PythonOps.Repr(context, DynamicHelpers.GetPythonType(type\u00F8)));
  119. if (args\u00F8 == null) args\u00F8 = new object[1];
  120. return overloads\u00F8.Call(context, storage, null, args\u00F8);
  121. }
  122. public static object OverloadedNewKW(CodeContext context, BuiltinFunction overloads\u00F8, PythonType type\u00F8, [ParamDictionary]IDictionary<object, object> kwargs\u00F8) {
  123. if (type\u00F8 == null) throw PythonOps.TypeError("__new__ expected type object, got {0}", PythonOps.Repr(context, DynamicHelpers.GetPythonType(type\u00F8)));
  124. return overloads\u00F8.Call(context, null, null, ArrayUtils.EmptyObjects, kwargs\u00F8);
  125. }
  126. public static object OverloadedNewClsKW(CodeContext context, BuiltinFunction overloads\u00F8, PythonType type\u00F8, [ParamDictionary]IDictionary<object, object> kwargs\u00F8, params object[] args\u00F8) {
  127. if (type\u00F8 == null) throw PythonOps.TypeError("__new__ expected type object, got {0}", PythonOps.Repr(context, DynamicHelpers.GetPythonType(type\u00F8)));
  128. if (args\u00F8 == null) args\u00F8 = new object[1];
  129. return overloads\u00F8.Call(context, null, null, args\u00F8, kwargs\u00F8);
  130. }
  131. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "self"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "context"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "args\u00F8")]
  132. public static void DefaultInit(CodeContext context, object self, params object[] args\u00F8) {
  133. }
  134. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "self"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "kwargs\u00F8"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "context"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "args\u00F8")]
  135. public static void DefaultInitKW(CodeContext context, object self, [ParamDictionary]IDictionary<object, object> kwargs\u00F8, params object[] args\u00F8) {
  136. }
  137. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "context")]
  138. [StaticExtensionMethod]
  139. public static object NonDefaultNew(CodeContext context, PythonType type\u00F8, params object[] args\u00F8) {
  140. if (type\u00F8 == null) throw PythonOps.TypeError("__new__ expected type object, got {0}", PythonOps.Repr(context, DynamicHelpers.GetPythonType(type\u00F8)));
  141. if (args\u00F8 == null) args\u00F8 = new object[1];
  142. return type\u00F8.CreateInstance(context, args\u00F8);
  143. }
  144. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "context")]
  145. [StaticExtensionMethod]
  146. public static object NonDefaultNewKW(CodeContext context, PythonType type\u00F8, [ParamDictionary]IDictionary<object, object> kwargs\u00F8, params object[] args\u00F8) {
  147. if (type\u00F8 == null) throw PythonOps.TypeError("__new__ expected type object, got {0}", PythonOps.Repr(context, DynamicHelpers.GetPythonType(type\u00F8)));
  148. if (args\u00F8 == null) args\u00F8 = new object[1];
  149. string []names;
  150. GetKeywordArgs(kwargs\u00F8, args\u00F8, out args\u00F8, out names);
  151. return type\u00F8.CreateInstance(context, args\u00F8, names);
  152. }
  153. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "context")]
  154. [StaticExtensionMethod]
  155. public static object NonDefaultNewKWNoParams(CodeContext context, PythonType type\u00F8, [ParamDictionary]IDictionary<object, object> kwargs\u00F8) {
  156. if (type\u00F8 == null) throw PythonOps.TypeError("__new__ expected type object, got {0}", PythonOps.Repr(context, DynamicHelpers.GetPythonType(type\u00F8)));
  157. string[] names;
  158. object[] args;
  159. GetKeywordArgs(kwargs\u00F8, ArrayUtils.EmptyObjects, out args, out names);
  160. return type\u00F8.CreateInstance(context, args, names);
  161. }
  162. #endregion
  163. #region Iteration
  164. // 3.0-only
  165. public static object IterMethodForString(string self) {
  166. return PythonOps.StringEnumerator(self);
  167. }
  168. // 3.0-only
  169. public static object IterMethodForBytes(Bytes self) {
  170. return PythonOps.BytesIntEnumerator(self);
  171. }
  172. public static object IterMethodForEnumerator(IEnumerator self) {
  173. return self;
  174. }
  175. public static object IterMethodForEnumerable(IEnumerable self) {
  176. return self.GetEnumerator();
  177. }
  178. public static object IterMethodForGenericEnumerator<T>(IEnumerator<T> self) {
  179. return self;
  180. }
  181. public static object IterMethodForGenericEnumerable<T>(IEnumerable<T> self) {
  182. return self.GetEnumerator();
  183. }
  184. public static object NextMethod(object self) {
  185. IEnumerator i = (IEnumerator)self;
  186. if (i.MoveNext()) return i.Current;
  187. throw PythonOps.StopIteration();
  188. }
  189. #endregion
  190. /// <summary>
  191. /// __dir__(self) -> Returns the list of members defined on a foreign IDynamicMetaObjectProvider.
  192. /// </summary>
  193. public static List DynamicDir(CodeContext/*!*/ context, IDynamicMetaObjectProvider self) {
  194. List res = new List(self.GetMetaObject(Expression.Parameter(typeof(object))).GetDynamicMemberNames());
  195. // add in the non-dynamic members from the dynamic objects base class.
  196. Type t = self.GetType();
  197. while (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(t)) {
  198. t = t.BaseType;
  199. }
  200. res.extend(DynamicHelpers.GetPythonTypeFromType(t).GetMemberNames(context));
  201. res.sort(context);
  202. return res;
  203. }
  204. public static int LengthMethod(ICollection self) {
  205. return self.Count;
  206. }
  207. public static int GenericLengthMethod<T>(ICollection<T> self) {
  208. return self.Count;
  209. }
  210. #region Representation and Formatting
  211. public static string SimpleRepr(object self) {
  212. return String.Format("<{0} object at {1}>",
  213. PythonTypeOps.GetName(self),
  214. PythonOps.HexId(self));
  215. }
  216. public static string FancyRepr(object self) {
  217. PythonType pt = (PythonType)DynamicHelpers.GetPythonType(self);
  218. // we can't call ToString on a UserType because we'll stack overflow, so
  219. // only do FancyRepr for reflected types.
  220. if (pt.IsSystemType) {
  221. string toStr = self.ToString();
  222. if (toStr == null) toStr = String.Empty;
  223. // get the type name to display (CLI name or Python name)
  224. Type type = pt.UnderlyingSystemType;
  225. string typeName = type.FullName;
  226. // Get the underlying .ToString() representation. Truncate multiple
  227. // lines, and don't display it if it's object's default representation (type name)
  228. // skip initial empty lines:
  229. int i = 0;
  230. while (i < toStr.Length && (toStr[i] == '\r' || toStr[i] == '\n')) i++;
  231. // read the first non-empty line:
  232. int j = i;
  233. while (j < toStr.Length && toStr[j] != '\r' && toStr[j] != '\n') j++;
  234. // skip following empty lines:
  235. int k = j;
  236. while (k < toStr.Length && (toStr[k] == '\r' || toStr[k] == '\n')) k++;
  237. if (j > i) {
  238. string first_non_empty_line = toStr.Substring(i, j - i);
  239. bool has_multiple_non_empty_lines = k < toStr.Length;
  240. return String.Format("<{0} object at {1} [{2}{3}]>",
  241. typeName,
  242. PythonOps.HexId(self),
  243. first_non_empty_line,
  244. has_multiple_non_empty_lines ? "..." : String.Empty);
  245. } else {
  246. return String.Format("<{0} object at {1}>",
  247. typeName,
  248. PythonOps.HexId(self));
  249. }
  250. }
  251. return SimpleRepr(self);
  252. }
  253. public static object ReprHelper(CodeContext context, object self) {
  254. return ((ICodeFormattable)self).__repr__(context);
  255. }
  256. public static string ToStringMethod(object self) {
  257. string res = self.ToString();
  258. if (res == null) return String.Empty;
  259. return res;
  260. }
  261. public static string Format(IFormattable formattable, string format) {
  262. return formattable.ToString(format, null);
  263. }
  264. #endregion
  265. #region Comparison and Hashing
  266. #if CLR2
  267. // Value equality helpers: These are the default implementation for classes that implement
  268. // IValueEquality. We promote the ReflectedType to having these helper methods which will
  269. // automatically test the type and return NotImplemented for mixed comparisons. For non-mixed
  270. // comparisons we have a fully optimized version which returns bool.
  271. public static bool ValueEqualsMethod<T>(T x, [NotNull]T y)
  272. where T : IValueEquality {
  273. return x.ValueEquals(y);
  274. }
  275. public static bool ValueNotEqualsMethod<T>(T x, [NotNull]T y)
  276. where T : IValueEquality {
  277. return !x.ValueEquals(y);
  278. }
  279. [return: MaybeNotImplemented]
  280. public static object ValueEqualsMethod<T>([NotNull]T x, object y)
  281. where T : IValueEquality {
  282. if (!(y is T)) return NotImplementedType.Value;
  283. return ScriptingRuntimeHelpers.BooleanToObject(x.ValueEquals(y));
  284. }
  285. [return: MaybeNotImplemented]
  286. public static object ValueNotEqualsMethod<T>([NotNull]T x, object y)
  287. where T : IValueEquality {
  288. if (!(y is T)) return NotImplementedType.Value;
  289. return ScriptingRuntimeHelpers.BooleanToObject(!x.ValueEquals(y));
  290. }
  291. [return: MaybeNotImplemented]
  292. public static object ValueEqualsMethod<T>(object y, [NotNull]T x)
  293. where T : IValueEquality {
  294. if (!(y is T)) return NotImplementedType.Value;
  295. return ScriptingRuntimeHelpers.BooleanToObject(x.ValueEquals(y));
  296. }
  297. [return: MaybeNotImplemented]
  298. public static object ValueNotEqualsMethod<T>(object y, [NotNull]T x)
  299. where T : IValueEquality {
  300. if (!(y is T)) return NotImplementedType.Value;
  301. return ScriptingRuntimeHelpers.BooleanToObject(!x.ValueEquals(y));
  302. }
  303. #endif
  304. public static bool EqualsMethod(object x, object y) {
  305. return x.Equals(y);
  306. }
  307. public static bool NotEqualsMethod(object x, object y) {
  308. return !x.Equals(y);
  309. }
  310. #if CLR2
  311. public static bool TypeNotEqualsMethod(Type x, object y) {
  312. ContractUtils.RequiresNotNull(x, "x");
  313. PythonType pythonType = y as PythonType;
  314. if (pythonType != null) {
  315. return !x.Equals((Type)pythonType);
  316. }
  317. Type type = y as Type;
  318. return y == null || !x.Equals(type);
  319. }
  320. #endif
  321. // Structural Equality and Hashing Helpers
  322. public static int StructuralHashMethod(CodeContext/*!*/ context, IStructuralEquatable x) {
  323. return x.GetHashCode(PythonContext.GetContext(context).EqualityComparerNonGeneric);
  324. }
  325. public static bool StructuralEqualityMethod<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  326. where T : IStructuralEquatable {
  327. return x.Equals(y, PythonContext.GetContext(context).EqualityComparerNonGeneric);
  328. }
  329. public static bool StructuralInequalityMethod<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  330. where T : IStructuralEquatable {
  331. return !x.Equals(y, PythonContext.GetContext(context).EqualityComparerNonGeneric);
  332. }
  333. [return: MaybeNotImplemented]
  334. public static object StructuralEqualityMethod<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  335. where T : IStructuralEquatable {
  336. if (!(y is T)) return NotImplementedType.Value;
  337. return ScriptingRuntimeHelpers.BooleanToObject(
  338. x.Equals(y, PythonContext.GetContext(context).EqualityComparerNonGeneric)
  339. );
  340. }
  341. [return: MaybeNotImplemented]
  342. public static object StructuralInequalityMethod<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  343. where T : IStructuralEquatable {
  344. if (!(y is T)) return NotImplementedType.Value;
  345. return ScriptingRuntimeHelpers.BooleanToObject(
  346. !x.Equals(y, PythonContext.GetContext(context).EqualityComparerNonGeneric)
  347. );
  348. }
  349. [return: MaybeNotImplemented]
  350. public static object StructuralEqualityMethod<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  351. where T : IStructuralEquatable {
  352. if (!(y is T)) return NotImplementedType.Value;
  353. return ScriptingRuntimeHelpers.BooleanToObject(
  354. x.Equals(y, PythonContext.GetContext(context).EqualityComparerNonGeneric)
  355. );
  356. }
  357. [return: MaybeNotImplemented]
  358. public static object StructuralInequalityMethod<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  359. where T : IStructuralEquatable {
  360. if (!(y is T)) return NotImplementedType.Value;
  361. return ScriptingRuntimeHelpers.BooleanToObject(
  362. !x.Equals(y, PythonContext.GetContext(context).EqualityComparerNonGeneric)
  363. );
  364. }
  365. // Structural Comparison Helpers
  366. private static int StructuralCompare(CodeContext/*!*/ context, IStructuralComparable x, object y) {
  367. return x.CompareTo(y, PythonContext.GetContext(context).GetComparer(null, null));
  368. }
  369. public static bool StructuralComparableEquality<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  370. where T : IStructuralComparable {
  371. return StructuralCompare(context, x, y) == 0;
  372. }
  373. public static bool StructuralComparableInequality<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  374. where T : IStructuralComparable {
  375. return StructuralCompare(context, x, y) != 0;
  376. }
  377. public static bool StructuralComparableGreaterThan<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  378. where T : IStructuralComparable {
  379. return StructuralCompare(context, x, y) > 0;
  380. }
  381. public static bool StructuralComparableLessThan<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  382. where T : IStructuralComparable {
  383. return StructuralCompare(context, x, y) < 0;
  384. }
  385. public static bool StructuralComparableGreaterEqual<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  386. where T : IStructuralComparable {
  387. return StructuralCompare(context, x, y) >= 0;
  388. }
  389. public static bool StructuralComparableLessEqual<T>(CodeContext/*!*/ context, T x, [NotNull]T y)
  390. where T : IStructuralComparable {
  391. return StructuralCompare(context, x, y) <= 0;
  392. }
  393. [return: MaybeNotImplemented]
  394. public static object StructuralComparableEquality<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  395. where T : IStructuralComparable {
  396. if (!(y is T)) return NotImplementedType.Value;
  397. return ScriptingRuntimeHelpers.BooleanToObject(
  398. StructuralCompare(context, x, y) == 0
  399. );
  400. }
  401. [return: MaybeNotImplemented]
  402. public static object StructuralComparableInequality<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  403. where T : IStructuralComparable {
  404. if (!(y is T)) return NotImplementedType.Value;
  405. return ScriptingRuntimeHelpers.BooleanToObject(
  406. StructuralCompare(context, x, y) != 0
  407. );
  408. }
  409. [return: MaybeNotImplemented]
  410. public static object StructuralComparableGreaterThan<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  411. where T : IStructuralComparable {
  412. if (!(y is T)) return NotImplementedType.Value;
  413. return ScriptingRuntimeHelpers.BooleanToObject(
  414. StructuralCompare(context, x, y) > 0
  415. );
  416. }
  417. [return: MaybeNotImplemented]
  418. public static object StructuralComparableLessThan<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  419. where T : IStructuralComparable {
  420. if (!(y is T)) return NotImplementedType.Value;
  421. return ScriptingRuntimeHelpers.BooleanToObject(
  422. StructuralCompare(context, x, y) < 0
  423. );
  424. }
  425. [return: MaybeNotImplemented]
  426. public static object StructuralComparableGreaterEqual<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  427. where T : IStructuralComparable {
  428. if (!(y is T)) return NotImplementedType.Value;
  429. return ScriptingRuntimeHelpers.BooleanToObject(
  430. StructuralCompare(context, x, y) >= 0
  431. );
  432. }
  433. [return: MaybeNotImplemented]
  434. public static object StructuralComparableLessEqual<T>(CodeContext/*!*/ context, [NotNull]T x, object y)
  435. where T : IStructuralComparable {
  436. if (!(y is T)) return NotImplementedType.Value;
  437. return ScriptingRuntimeHelpers.BooleanToObject(
  438. StructuralCompare(context, x, y) <= 0
  439. );
  440. }
  441. [return: MaybeNotImplemented]
  442. public static object StructuralComparableEquality<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  443. where T : IStructuralComparable {
  444. if (!(y is T)) return NotImplementedType.Value;
  445. return ScriptingRuntimeHelpers.BooleanToObject(
  446. StructuralCompare(context, x, y) == 0
  447. );
  448. }
  449. [return: MaybeNotImplemented]
  450. public static object StructuralComparableInequality<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  451. where T : IStructuralComparable {
  452. if (!(y is T)) return NotImplementedType.Value;
  453. return ScriptingRuntimeHelpers.BooleanToObject(
  454. StructuralCompare(context, x, y) != 0
  455. );
  456. }
  457. [return: MaybeNotImplemented]
  458. public static object StructuralComparableGreaterThan<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  459. where T : IStructuralComparable {
  460. if (!(y is T)) return NotImplementedType.Value;
  461. return ScriptingRuntimeHelpers.BooleanToObject(
  462. // operator direction is reversed
  463. StructuralCompare(context, x, y) < 0
  464. );
  465. }
  466. [return: MaybeNotImplemented]
  467. public static object StructuralComparableLessThan<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  468. where T : IStructuralComparable {
  469. if (!(y is T)) return NotImplementedType.Value;
  470. return ScriptingRuntimeHelpers.BooleanToObject(
  471. // operator direction is reversed
  472. StructuralCompare(context, x, y) > 0
  473. );
  474. }
  475. [return: MaybeNotImplemented]
  476. public static object StructuralComparableGreaterEqual<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  477. where T : IStructuralComparable {
  478. if (!(y is T)) return NotImplementedType.Value;
  479. return ScriptingRuntimeHelpers.BooleanToObject(
  480. // operator direction is reversed
  481. StructuralCompare(context, x, y) <= 0
  482. );
  483. }
  484. [return: MaybeNotImplemented]
  485. public static object StructuralComparableLessEqual<T>(CodeContext/*!*/ context, object y, [NotNull]T x)
  486. where T : IStructuralComparable {
  487. if (!(y is T)) return NotImplementedType.Value;
  488. return ScriptingRuntimeHelpers.BooleanToObject(
  489. // operator direction is reversed
  490. StructuralCompare(context, x, y) >= 0
  491. );
  492. }
  493. // Comparison Helpers
  494. public static bool ComparableEquality<T>(T x, [NotNull]T y)
  495. where T : IComparable {
  496. return x.CompareTo(y) == 0;
  497. }
  498. public static bool ComparableInequality<T>(T x, [NotNull]T y)
  499. where T : IComparable {
  500. return x.CompareTo(y) != 0;
  501. }
  502. public static bool ComparableGreaterThan<T>(T x, [NotNull]T y)
  503. where T : IComparable {
  504. return x.CompareTo(y) > 0;
  505. }
  506. public static bool ComparableLessThan<T>(T x, [NotNull]T y)
  507. where T : IComparable {
  508. return x.CompareTo(y) < 0;
  509. }
  510. public static bool ComparableGreaterEqual<T>(T x, [NotNull]T y)
  511. where T : IComparable {
  512. return x.CompareTo(y) >= 0;
  513. }
  514. public static bool ComparableLessEqual<T>(T x, [NotNull]T y)
  515. where T : IComparable {
  516. return x.CompareTo(y) <= 0;
  517. }
  518. [return: MaybeNotImplemented]
  519. public static object ComparableEquality<T>([NotNull]T x, object y)
  520. where T : IComparable {
  521. if (!(y is T)) return NotImplementedType.Value;
  522. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) == 0);
  523. }
  524. [return: MaybeNotImplemented]
  525. public static object ComparableInequality<T>([NotNull]T x, object y)
  526. where T : IComparable {
  527. if (!(y is T)) return NotImplementedType.Value;
  528. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) != 0);
  529. }
  530. [return: MaybeNotImplemented]
  531. public static object ComparableGreaterThan<T>([NotNull]T x, object y)
  532. where T : IComparable {
  533. if (!(y is T)) return NotImplementedType.Value;
  534. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) > 0);
  535. }
  536. [return: MaybeNotImplemented]
  537. public static object ComparableLessThan<T>([NotNull]T x, object y)
  538. where T : IComparable {
  539. if (!(y is T)) return NotImplementedType.Value;
  540. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) < 0);
  541. }
  542. [return: MaybeNotImplemented]
  543. public static object ComparableGreaterEqual<T>([NotNull]T x, object y)
  544. where T : IComparable {
  545. if (!(y is T)) return NotImplementedType.Value;
  546. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) >= 0);
  547. }
  548. [return: MaybeNotImplemented]
  549. public static object ComparableLessEqual<T>([NotNull]T x, object y)
  550. where T : IComparable {
  551. if (!(y is T)) return NotImplementedType.Value;
  552. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) <= 0);
  553. }
  554. [return: MaybeNotImplemented]
  555. public static object ComparableEquality<T>(object y, [NotNull]T x)
  556. where T : IComparable {
  557. if (!(y is T)) return NotImplementedType.Value;
  558. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) == 0);
  559. }
  560. [return: MaybeNotImplemented]
  561. public static object ComparableInequality<T>(object y, [NotNull]T x)
  562. where T : IComparable {
  563. if (!(y is T)) return NotImplementedType.Value;
  564. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) != 0);
  565. }
  566. [return: MaybeNotImplemented]
  567. public static object ComparableGreaterThan<T>(object y, [NotNull]T x)
  568. where T : IComparable {
  569. if (!(y is T)) return NotImplementedType.Value;
  570. // operator direction is reversed
  571. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) < 0);
  572. }
  573. [return: MaybeNotImplemented]
  574. public static object ComparableLessThan<T>(object y, [NotNull]T x)
  575. where T : IComparable {
  576. if (!(y is T)) return NotImplementedType.Value;
  577. // operator direction is reversed
  578. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) > 0);
  579. }
  580. [return: MaybeNotImplemented]
  581. public static object ComparableGreaterEqual<T>(object y, [NotNull]T x)
  582. where T : IComparable {
  583. if (!(y is T)) return NotImplementedType.Value;
  584. // operator direction is reversed
  585. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) <= 0);
  586. }
  587. [return: MaybeNotImplemented]
  588. public static object ComparableLessEqual<T>(object y, [NotNull]T x)
  589. where T : IComparable {
  590. if (!(y is T)) return NotImplementedType.Value;
  591. // operator direction is reversed
  592. return ScriptingRuntimeHelpers.BooleanToObject(x.CompareTo(y) >= 0);
  593. }
  594. #endregion
  595. /// <summary>
  596. /// Provides the implementation of __enter__ for objects which implement IDisposable.
  597. /// </summary>
  598. public static object EnterMethod(IDisposable/*!*/ self) {
  599. return self;
  600. }
  601. /// <summary>
  602. /// Provides the implementation of __exit__ for objects which implement IDisposable.
  603. /// </summary>
  604. public static void ExitMethod(IDisposable/*!*/ self, object exc_type, object exc_value, object exc_back) {
  605. self.Dispose();
  606. }
  607. [PropertyMethod, StaticExtensionMethod]
  608. public static List/*!*/ Get__all__<T>(CodeContext/*!*/ context) {
  609. Debug.Assert(typeof(T).IsSealed && typeof(T).IsAbstract, "__all__ should only be produced for static members");
  610. PythonType pt = DynamicHelpers.GetPythonTypeFromType(typeof(T));
  611. List names = new List();
  612. foreach (string name in pt.GetMemberNames(context)) {
  613. object res;
  614. if (IsStaticTypeMemberInAll(context, pt, name, out res)) {
  615. names.AddNoLock(name);
  616. }
  617. }
  618. return names;
  619. }
  620. /// <summary>
  621. /// Determines if a type member can be imported. This is used to treat static types like modules.
  622. /// </summary>
  623. private static bool IsStaticTypeMemberInAll(CodeContext/*!*/ context, PythonType/*!*/ pt, string name, out object res) {
  624. PythonTypeSlot pts;
  625. res = null;
  626. if (pt.TryResolveSlot(context, name, out pts)) {
  627. if (name == "__doc__" || name == "__class__") {
  628. // these exist but we don't want to clobber __doc__ on import * or bring in __class__
  629. return false;
  630. } else if (pts is ReflectedGetterSetter) {
  631. // property or indexer, these fetch the value at runtime, the user needs to explicitly
  632. // import them using from type import property
  633. return false;
  634. }
  635. ReflectedField rf = pts as ReflectedField;
  636. if (rf != null && !rf._info.IsInitOnly && !rf._info.IsLiteral) {
  637. // only bring in read-only fields, if the value can change the user needs to explicitly
  638. // import by name
  639. return false;
  640. }
  641. BuiltinMethodDescriptor method = pts as BuiltinMethodDescriptor;
  642. if (method != null && (!method.DeclaringType.IsSealed || !method.DeclaringType.IsAbstract)) {
  643. // inherited object member on a static class (GetHashCode, Equals, etc...)
  644. return false;
  645. }
  646. BuiltinFunction bf = pts as BuiltinFunction;
  647. if (bf != null && (!bf.DeclaringType.IsSealed || !bf.DeclaringType.IsAbstract)) {
  648. // __new__/ReferenceEquals inherited from object
  649. return false;
  650. }
  651. if (pts.TryGetValue(context, null, pt, out res)) {
  652. return true;
  653. }
  654. }
  655. res = null;
  656. return false;
  657. }
  658. #region Contains
  659. /// <summary>
  660. /// Implements __contains__ for types implementing IEnumerable of T.
  661. /// </summary>
  662. public static bool ContainsGenericMethod<T>(CodeContext/*!*/ context, IEnumerable<T> enumerable, T value) {
  663. foreach(T item in enumerable) {
  664. if (PythonOps.EqualRetBool(context, item, value)) {
  665. return true;
  666. }
  667. }
  668. return false;
  669. }
  670. /// <summary>
  671. /// Implements __contains__ for types implementing IEnumerable
  672. /// </summary>
  673. public static bool ContainsMethod(CodeContext/*!*/ context, IEnumerable enumerable, object value) {
  674. IEnumerator ie = enumerable.GetEnumerator();
  675. while (ie.MoveNext()) {
  676. if (PythonOps.EqualRetBool(context, ie.Current, value)) {
  677. return true;
  678. }
  679. }
  680. return false;
  681. }
  682. /// <summary>
  683. /// Implements __contains__ for types implementing IEnumerable of T.
  684. /// </summary>
  685. public static bool ContainsGenericMethodIEnumerator<T>(CodeContext/*!*/ context, IEnumerator<T> enumerator, T value) {
  686. while (enumerator.MoveNext()) {
  687. if (PythonOps.EqualRetBool(context, enumerator.Current, value)) {
  688. return true;
  689. }
  690. }
  691. return false;
  692. }
  693. /// <summary>
  694. /// Implements __contains__ for types implementing IEnumerable
  695. /// </summary>
  696. public static bool ContainsMethodIEnumerator(CodeContext/*!*/ context, IEnumerator enumerator, object value) {
  697. while (enumerator.MoveNext()) {
  698. if (PythonOps.EqualRetBool(context, enumerator.Current, value)) {
  699. return true;
  700. }
  701. }
  702. return false;
  703. }
  704. #endregion
  705. #if !SILVERLIGHT
  706. /// <summary>
  707. /// Implements __reduce_ex__ for .NET types which are serializable. This uses the .NET
  708. /// serializer to get a string of raw data which can be serialized.
  709. /// </summary>
  710. public static PythonTuple SerializeReduce(CodeContext/*!*/ context, object/*!*/ self, int protocol) {
  711. PythonTuple data = ClrModule.Serialize(self);
  712. object deserializeNew;
  713. bool res = PythonContext.GetContext(context).ClrModule.__dict__.TryGetValue(
  714. "Deserialize",
  715. out deserializeNew
  716. );
  717. Debug.Assert(res);
  718. return PythonTuple.MakeTuple(
  719. deserializeNew, // function to call, clr.DeserializeNew
  720. data, // data to pass to it - our type & the raw data from the .NET serializer
  721. null // state, unused
  722. );
  723. }
  724. #endif
  725. internal const string ObjectNewNoParameters = "object.__new__() takes no parameters";
  726. internal static void CheckNewArgs(CodeContext context, IDictionary<object, object> dict, object[] args, PythonType pt) {
  727. if (((args != null && args.Length > 0) || (dict != null && dict.Count > 0))) {
  728. bool hasObjectInit = pt.HasObjectInit(context);
  729. bool hasObjectNew = pt.HasObjectNew(context);
  730. if (hasObjectInit) {
  731. throw PythonOps.TypeError(ObjectNewNoParameters);
  732. } else if (!hasObjectNew && !hasObjectInit) {
  733. PythonOps.Warn(context, PythonExceptions.DeprecationWarning, ObjectNewNoParameters);
  734. }
  735. }
  736. }
  737. internal static void CheckInitArgs(CodeContext context, IDictionary<object, object> dict, object[] args, object self) {
  738. if (((args != null && args.Length > 0) || (dict != null && dict.Count > 0))) {
  739. PythonType pt = DynamicHelpers.GetPythonType(self);
  740. bool hasObjectInit = pt.HasObjectInit(context);
  741. bool hasObjectNew = pt.HasObjectNew(context);
  742. // NoneType seems to get some special treatment (None.__init__('abc') works)
  743. if (hasObjectNew && self != null) {
  744. throw PythonOps.TypeError("object.__init__() takes no parameters");
  745. } else if ((!hasObjectNew && !hasObjectInit) || self == null) {
  746. PythonOps.Warn(context, PythonExceptions.DeprecationWarning, "object.__init__() takes no parameters for type {0}", PythonTypeOps.GetName(self));
  747. }
  748. }
  749. }
  750. private static BuiltinMethodDescriptor GetInitMethod() {
  751. PythonTypeSlot pts;
  752. TypeCache.Object.TryResolveSlot(DefaultContext.Default, "__init__", out pts);
  753. Debug.Assert(pts != null);
  754. return (BuiltinMethodDescriptor)pts;
  755. }
  756. private static BuiltinFunction CreateFunction(string name, params string[] methodNames) {
  757. MethodBase[] methods = new MethodBase[methodNames.Length];
  758. for (int i = 0; i < methods.Length; i++) {
  759. methods[i] = typeof(InstanceOps).GetMethod(methodNames[i]);
  760. }
  761. return BuiltinFunction.MakeFunction(name, methods, typeof(object));
  762. }
  763. private static void GetKeywordArgs(IDictionary<object, object> dict, object[] args, out object[] finalArgs, out string[] names) {
  764. finalArgs = new object[args.Length + dict.Count];
  765. Array.Copy(args, finalArgs, args.Length);
  766. names = new string[dict.Count];
  767. int i = 0;
  768. foreach (KeyValuePair<object, object> kvp in dict) {
  769. names[i] = (string)kvp.Key;
  770. finalArgs[i + args.Length] = kvp.Value;
  771. i++;
  772. }
  773. }
  774. }
  775. }