PageRenderTime 40ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/Types/OldInstance.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 998 lines | 758 code | 208 blank | 32 comment | 150 complexity | 03ffdbbc63112038522de6eede377dbc 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. using System.Numerics;
  18. #else
  19. using Microsoft.Scripting.Ast;
  20. using Microsoft.Scripting.Math;
  21. #endif
  22. using System;
  23. using System.Collections;
  24. using System.Collections.Generic;
  25. using System.ComponentModel;
  26. using System.Diagnostics;
  27. using System.Dynamic;
  28. using System.Runtime.Serialization;
  29. using System.Security.Permissions;
  30. using Microsoft.Scripting;
  31. using Microsoft.Scripting.Runtime;
  32. using Microsoft.Scripting.Utils;
  33. using IronPython.Runtime.Operations;
  34. using SpecialNameAttribute = System.Runtime.CompilerServices.SpecialNameAttribute;
  35. namespace IronPython.Runtime.Types {
  36. [PythonType("instance")]
  37. [Serializable]
  38. [DebuggerTypeProxy(typeof(OldInstance.OldInstanceDebugView)), DebuggerDisplay("old-style instance of {ClassName}")]
  39. public sealed partial class OldInstance :
  40. ICodeFormattable,
  41. #if CLR2
  42. IValueEquality,
  43. #endif
  44. #if !SILVERLIGHT // ICustomTypeDescriptor
  45. ICustomTypeDescriptor,
  46. #endif
  47. ISerializable,
  48. IWeakReferenceable,
  49. IDynamicMetaObjectProvider,
  50. IPythonMembersList
  51. {
  52. private PythonDictionary _dict;
  53. internal OldClass _class;
  54. private WeakRefTracker _weakRef; // initialized if user defines finalizer on class or instance
  55. private static PythonDictionary MakeDictionary(OldClass oldClass) {
  56. return new PythonDictionary(new CustomInstanceDictionaryStorage(oldClass.OptimizedInstanceNames, oldClass.OptimizedInstanceNamesVersion));
  57. }
  58. public OldInstance(CodeContext/*!*/ context, OldClass @class) {
  59. _class = @class;
  60. _dict = MakeDictionary(@class);
  61. if (_class.HasFinalizer) {
  62. // class defines finalizer, we get it automatically.
  63. AddFinalizer(context);
  64. }
  65. }
  66. public OldInstance(CodeContext/*!*/ context, OldClass @class, PythonDictionary dict) {
  67. _class = @class;
  68. _dict = dict ?? PythonDictionary.MakeSymbolDictionary();
  69. if (_class.HasFinalizer) {
  70. // class defines finalizer, we get it automatically.
  71. AddFinalizer(context);
  72. }
  73. }
  74. #if !SILVERLIGHT // SerializationInfo
  75. private OldInstance(SerializationInfo info, StreamingContext context) {
  76. _class = (OldClass)info.GetValue("__class__", typeof(OldClass));
  77. _dict = MakeDictionary(_class);
  78. List<object> keys = (List<object>)info.GetValue("keys", typeof(List<object>));
  79. List<object> values = (List<object>)info.GetValue("values", typeof(List<object>));
  80. for (int i = 0; i < keys.Count; i++) {
  81. _dict[keys[i]] = values[i];
  82. }
  83. }
  84. #pragma warning disable 169 // unused method - called via reflection from serialization
  85. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "context")]
  86. private void GetObjectData(SerializationInfo info, StreamingContext context) {
  87. ContractUtils.RequiresNotNull(info, "info");
  88. info.AddValue("__class__", _class);
  89. List<object> keys = new List<object>();
  90. List<object> values = new List<object>();
  91. foreach (object o in _dict.keys()) {
  92. keys.Add(o);
  93. object value;
  94. bool res = ((IAttributesCollection)_dict).TryGetObjectValue(o, out value);
  95. Debug.Assert(res);
  96. values.Add(value);
  97. }
  98. info.AddValue("keys", keys);
  99. info.AddValue("values", values);
  100. }
  101. #pragma warning restore 169
  102. #endif
  103. /// <summary>
  104. /// Returns the dictionary used to store state for this object
  105. /// </summary>
  106. internal PythonDictionary Dictionary {
  107. get { return _dict; }
  108. }
  109. internal string ClassName {
  110. get {
  111. return _class.Name;
  112. }
  113. }
  114. public static bool operator true(OldInstance self) {
  115. return (bool)self.__nonzero__(DefaultContext.Default);
  116. }
  117. public static bool operator false(OldInstance self) {
  118. return !(bool)self.__nonzero__(DefaultContext.Default);
  119. }
  120. #region Object overrides
  121. public override string ToString() {
  122. object ret = InvokeOne(this, "__str__");
  123. if (ret != NotImplementedType.Value) {
  124. string strRet;
  125. if (Converter.TryConvertToString(ret, out strRet) && strRet != null) {
  126. return strRet;
  127. }
  128. throw PythonOps.TypeError("__str__ returned non-string type ({0})", PythonTypeOps.GetName(ret));
  129. }
  130. return __repr__(DefaultContext.Default);
  131. }
  132. #endregion
  133. #region ICodeFormattable Members
  134. public string/*!*/ __repr__(CodeContext/*!*/ context) {
  135. object ret = InvokeOne(this, "__repr__");
  136. if(ret != NotImplementedType.Value) {
  137. string strRet;
  138. if (Converter.TryConvertToString(ret, out strRet) && strRet != null) {
  139. return strRet;
  140. }
  141. throw PythonOps.TypeError("__repr__ returned non-string type ({0})", PythonTypeOps.GetName(ret));
  142. }
  143. return string.Format("<{0} instance at {1}>", _class.FullName, PythonOps.HexId(this));
  144. }
  145. #endregion
  146. [return: MaybeNotImplemented]
  147. public object __divmod__(CodeContext context, object divmod) {
  148. object value;
  149. if (TryGetBoundCustomMember(context, "__divmod__", out value)) {
  150. return PythonCalls.Call(context, value, divmod);
  151. }
  152. return NotImplementedType.Value;
  153. }
  154. [return: MaybeNotImplemented]
  155. public static object __rdivmod__(CodeContext context, object divmod, [NotNull]OldInstance self) {
  156. object value;
  157. if (self.TryGetBoundCustomMember(context, "__rdivmod__", out value)) {
  158. return PythonCalls.Call(context, value, divmod);
  159. }
  160. return NotImplementedType.Value;
  161. }
  162. public object __coerce__(CodeContext context, object other) {
  163. object value;
  164. if (TryGetBoundCustomMember(context, "__coerce__", out value)) {
  165. return PythonCalls.Call(context, value, other);
  166. }
  167. return NotImplementedType.Value;
  168. }
  169. public object __len__(CodeContext context) {
  170. object value;
  171. if (TryGetBoundCustomMember(context, "__len__", out value)) {
  172. return PythonOps.CallWithContext(context, value);
  173. }
  174. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__len__");
  175. }
  176. public object __pos__(CodeContext context) {
  177. object value;
  178. if (TryGetBoundCustomMember(context, "__pos__", out value)) {
  179. return PythonOps.CallWithContext(context, value);
  180. }
  181. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__pos__");
  182. }
  183. [SpecialName]
  184. public object GetItem(CodeContext context, object item) {
  185. return PythonOps.Invoke(context, this, "__getitem__", item);
  186. }
  187. [SpecialName]
  188. public void SetItem(CodeContext context, object item, object value) {
  189. PythonOps.Invoke(context, this, "__setitem__", item, value);
  190. }
  191. [SpecialName]
  192. public object DeleteItem(CodeContext context, object item) {
  193. object value;
  194. if (TryGetBoundCustomMember(context, "__delitem__", out value)) {
  195. return PythonCalls.Call(context, value, item);
  196. }
  197. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__delitem__");
  198. }
  199. public object __getslice__(CodeContext context, int i, int j) {
  200. object callable;
  201. if (TryRawGetAttr(context, "__getslice__", out callable)) {
  202. return PythonCalls.Call(context, callable, i, j);
  203. } else if (TryRawGetAttr(context, "__getitem__", out callable)) {
  204. return PythonCalls.Call(context, callable, new Slice(i, j));
  205. }
  206. throw PythonOps.TypeError("instance {0} does not have __getslice__ or __getitem__", _class.Name);
  207. }
  208. public void __setslice__(CodeContext context, int i, int j, object value) {
  209. object callable;
  210. if (TryRawGetAttr(context, "__setslice__", out callable)) {
  211. PythonCalls.Call(context, callable, i, j, value);
  212. return;
  213. } else if (TryRawGetAttr(context, "__setitem__", out callable)) {
  214. PythonCalls.Call(context, callable, new Slice(i, j), value);
  215. return;
  216. }
  217. throw PythonOps.TypeError("instance {0} does not have __setslice__ or __setitem__", _class.Name);
  218. }
  219. public object __delslice__(CodeContext context, int i, int j) {
  220. object callable;
  221. if (TryRawGetAttr(context, "__delslice__", out callable)) {
  222. return PythonCalls.Call(context, callable, i, j);
  223. } else if (TryRawGetAttr(context, "__delitem__", out callable)) {
  224. return PythonCalls.Call(context, callable, new Slice(i, j));
  225. }
  226. throw PythonOps.TypeError("instance {0} does not have __delslice__ or __delitem__", _class.Name);
  227. }
  228. public object __index__(CodeContext context) {
  229. object value;
  230. if (TryGetBoundCustomMember(context, "__int__", out value)) {
  231. return PythonOps.CallWithContext(context, value);
  232. }
  233. throw PythonOps.TypeError("object cannot be converted to an index");
  234. }
  235. public object __neg__(CodeContext context) {
  236. object value;
  237. if (TryGetBoundCustomMember(context, "__neg__", out value)) {
  238. return PythonOps.CallWithContext(context, value);
  239. }
  240. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__neg__");
  241. }
  242. public object __abs__(CodeContext context) {
  243. object value;
  244. if (TryGetBoundCustomMember(context, "__abs__", out value)) {
  245. return PythonOps.CallWithContext(context, value);
  246. }
  247. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__abs__");
  248. }
  249. public object __invert__(CodeContext context) {
  250. object value;
  251. if (TryGetBoundCustomMember(context, "__invert__", out value)) {
  252. return PythonOps.CallWithContext(context, value);
  253. }
  254. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__invert__");
  255. }
  256. public object __contains__(CodeContext context, object index) {
  257. object value;
  258. if (TryGetBoundCustomMember(context, "__contains__", out value)) {
  259. return PythonCalls.Call(context, value, index);
  260. }
  261. IEnumerator ie = PythonOps.GetEnumerator(this);
  262. while (ie.MoveNext()) {
  263. if (PythonOps.EqualRetBool(context, ie.Current, index)) return ScriptingRuntimeHelpers.True;
  264. }
  265. return ScriptingRuntimeHelpers.False;
  266. }
  267. [SpecialName]
  268. public object Call(CodeContext context) {
  269. return Call(context, ArrayUtils.EmptyObjects);
  270. }
  271. [SpecialName]
  272. public object Call(CodeContext context, object args) {
  273. try {
  274. PythonOps.FunctionPushFrame(PythonContext.GetContext(context));
  275. object value;
  276. if (TryGetBoundCustomMember(context, "__call__", out value)) {
  277. return PythonOps.CallWithContext(context, value, args);
  278. }
  279. } finally {
  280. PythonOps.FunctionPopFrame();
  281. }
  282. throw PythonOps.AttributeError("{0} instance has no __call__ method", _class.Name);
  283. }
  284. [SpecialName]
  285. public object Call(CodeContext context, params object[] args) {
  286. try {
  287. PythonOps.FunctionPushFrame(PythonContext.GetContext(context));
  288. object value;
  289. if (TryGetBoundCustomMember(context, "__call__", out value)) {
  290. return PythonOps.CallWithContext(context, value, args);
  291. }
  292. } finally {
  293. PythonOps.FunctionPopFrame();
  294. }
  295. throw PythonOps.AttributeError("{0} instance has no __call__ method", _class.Name);
  296. }
  297. [SpecialName]
  298. public object Call(CodeContext context, [ParamDictionary]IDictionary<object, object> dict, params object[] args) {
  299. try {
  300. PythonOps.FunctionPushFrame(PythonContext.GetContext(context));
  301. object value;
  302. if (TryGetBoundCustomMember(context, "__call__", out value)) {
  303. return context.LanguageContext.CallWithKeywords(value, args, dict);
  304. }
  305. } finally {
  306. PythonOps.FunctionPopFrame();
  307. }
  308. throw PythonOps.AttributeError("{0} instance has no __call__ method", _class.Name);
  309. }
  310. public object __nonzero__(CodeContext context) {
  311. object value;
  312. if (TryGetBoundCustomMember(context, "__nonzero__", out value)) {
  313. return PythonOps.CallWithContext(context, value);
  314. }
  315. if (TryGetBoundCustomMember(context, "__len__", out value)) {
  316. value = PythonOps.CallWithContext(context, value);
  317. // Convert resulting object to the desired type
  318. if (value is Int32 || value is BigInteger) {
  319. return ScriptingRuntimeHelpers.BooleanToObject(Converter.ConvertToBoolean(value));
  320. }
  321. throw PythonOps.TypeError("an integer is required, got {0}", PythonTypeOps.GetName(value));
  322. }
  323. return ScriptingRuntimeHelpers.True;
  324. }
  325. public object __hex__(CodeContext context) {
  326. object value;
  327. if (TryGetBoundCustomMember(context, "__hex__", out value)) {
  328. return PythonOps.CallWithContext(context, value);
  329. }
  330. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__hex__");
  331. }
  332. public object __oct__(CodeContext context) {
  333. object value;
  334. if (TryGetBoundCustomMember(context, "__oct__", out value)) {
  335. return PythonOps.CallWithContext(context, value);
  336. }
  337. throw PythonOps.AttributeErrorForOldInstanceMissingAttribute(_class.Name, "__oct__");
  338. }
  339. public object __int__(CodeContext context) {
  340. object value;
  341. if (PythonOps.TryGetBoundAttr(context, this, "__int__", out value)) {
  342. return PythonOps.CallWithContext(context, value);
  343. }
  344. return NotImplementedType.Value;
  345. }
  346. public object __long__(CodeContext context) {
  347. object value;
  348. if (PythonOps.TryGetBoundAttr(context, this, "__long__", out value)) {
  349. return PythonOps.CallWithContext(context, value);
  350. }
  351. return NotImplementedType.Value;
  352. }
  353. public object __float__(CodeContext context) {
  354. object value;
  355. if (PythonOps.TryGetBoundAttr(context, this, "__float__", out value)) {
  356. return PythonOps.CallWithContext(context, value);
  357. }
  358. return NotImplementedType.Value;
  359. }
  360. public object __complex__(CodeContext context) {
  361. object value;
  362. if (TryGetBoundCustomMember(context, "__complex__", out value)) {
  363. return PythonOps.CallWithContext(context, value);
  364. }
  365. return NotImplementedType.Value;
  366. }
  367. public object __getattribute__(CodeContext context, string name) {
  368. object res;
  369. if (TryGetBoundCustomMember(context, name, out res)) {
  370. return res;
  371. }
  372. throw PythonOps.AttributeError("{0} instance has no attribute '{1}'", _class._name, name);
  373. }
  374. internal object GetBoundMember(CodeContext context, string name) {
  375. object ret;
  376. if (TryGetBoundCustomMember(context, name, out ret)) {
  377. return ret;
  378. }
  379. throw PythonOps.AttributeError("'{0}' object has no attribute '{1}'",
  380. PythonTypeOps.GetName(this), name);
  381. }
  382. #region ICustomMembers Members
  383. internal bool TryGetBoundCustomMember(CodeContext context, string name, out object value) {
  384. if (name == "__dict__") {
  385. //!!! user code can modify __del__ property of __dict__ behind our back
  386. value = _dict;
  387. return true;
  388. } else if (name == "__class__") {
  389. value = _class;
  390. return true;
  391. }
  392. if (TryRawGetAttr(context, name, out value)) return true;
  393. if (name != "__getattr__") {
  394. object getattr;
  395. if (TryRawGetAttr(context, "__getattr__", out getattr)) {
  396. try {
  397. value = PythonCalls.Call(context, getattr, name);
  398. return true;
  399. } catch (MissingMemberException) {
  400. // __getattr__ raised AttributeError, return false.
  401. }
  402. }
  403. }
  404. return false;
  405. }
  406. internal void SetCustomMember(CodeContext context, string name, object value) {
  407. object setFunc;
  408. if (name == "__class__") {
  409. SetClass(value);
  410. } else if (name == "__dict__") {
  411. SetDict(context, value);
  412. } else if (_class.HasSetAttr && _class.TryLookupSlot("__setattr__", out setFunc)) {
  413. PythonCalls.Call(context, _class.GetOldStyleDescriptor(context, setFunc, this, _class), name.ToString(), value);
  414. } else if (name == "__del__") {
  415. SetFinalizer(context, name, value);
  416. } else {
  417. _dict[name] = value;
  418. }
  419. }
  420. private void SetFinalizer(CodeContext/*!*/ context, string name, object value) {
  421. if (!HasFinalizer()) {
  422. // user is defining __del__ late bound for the 1st time
  423. AddFinalizer(context);
  424. }
  425. _dict[name] = value;
  426. }
  427. private void SetDict(CodeContext/*!*/ context, object value) {
  428. PythonDictionary dict = value as PythonDictionary;
  429. if (dict == null) {
  430. throw PythonOps.TypeError("__dict__ must be set to a dictionary");
  431. }
  432. if (HasFinalizer() && !_class.HasFinalizer) {
  433. if (!dict.ContainsKey("__del__")) {
  434. ClearFinalizer();
  435. }
  436. } else if (dict.ContainsKey("__del__")) {
  437. AddFinalizer(context);
  438. }
  439. _dict = dict;
  440. }
  441. private void SetClass(object value) {
  442. OldClass oc = value as OldClass;
  443. if (oc == null) {
  444. throw PythonOps.TypeError("__class__ must be set to class");
  445. }
  446. _class = oc;
  447. }
  448. internal bool DeleteCustomMember(CodeContext context, string name) {
  449. if (name == "__class__") throw PythonOps.TypeError("__class__ must be set to class");
  450. if (name == "__dict__") throw PythonOps.TypeError("__dict__ must be set to a dictionary");
  451. object delFunc;
  452. if (_class.HasDelAttr && _class.TryLookupSlot("__delattr__", out delFunc)) {
  453. PythonCalls.Call(context, _class.GetOldStyleDescriptor(context, delFunc, this, _class), name.ToString());
  454. return true;
  455. }
  456. if (name == "__del__") {
  457. // removing finalizer
  458. if (HasFinalizer() && !_class.HasFinalizer) {
  459. ClearFinalizer();
  460. }
  461. }
  462. if (!_dict.Remove(name)) {
  463. throw PythonOps.AttributeError("{0} is not a valid attribute", name);
  464. }
  465. return true;
  466. }
  467. #endregion
  468. #region IMembersList Members
  469. IList<string> IMembersList.GetMemberNames() {
  470. return PythonOps.GetStringMemberList(this);
  471. }
  472. IList<object> IPythonMembersList.GetMemberNames(CodeContext/*!*/ context) {
  473. PythonDictionary attrs = new PythonDictionary(_dict);
  474. OldClass.RecurseAttrHierarchy(this._class, attrs);
  475. return PythonOps.MakeListFromSequence(attrs);
  476. }
  477. #endregion
  478. [return: MaybeNotImplemented]
  479. public object __cmp__(CodeContext context, object other) {
  480. OldInstance oiOther = other as OldInstance;
  481. // CPython raises this if called directly, but not via cmp(os,ns) which still calls the user __cmp__
  482. //if(!(oiOther is OldInstance))
  483. // throw Ops.TypeError("instance.cmp(x,y) -> y must be an instance, got {0}", Ops.StringRepr(DynamicHelpers.GetPythonType(other)));
  484. object res = InternalCompare("__cmp__", other);
  485. if (res != NotImplementedType.Value) return res;
  486. if (oiOther != null) {
  487. res = oiOther.InternalCompare("__cmp__", this);
  488. if (res != NotImplementedType.Value) return ((int)res) * -1;
  489. }
  490. return NotImplementedType.Value;
  491. }
  492. private object CompareForwardReverse(object other, string forward, string reverse) {
  493. object res = InternalCompare(forward, other);
  494. if (res != NotImplementedType.Value) return res;
  495. OldInstance oi = other as OldInstance;
  496. if (oi != null) {
  497. // comparison operators are reflexive
  498. return oi.InternalCompare(reverse, this);
  499. }
  500. return NotImplementedType.Value;
  501. }
  502. [return: MaybeNotImplemented]
  503. public static object operator >([NotNull]OldInstance self, object other) {
  504. return self.CompareForwardReverse(other, "__gt__", "__lt__");
  505. }
  506. [return: MaybeNotImplemented]
  507. public static object operator <([NotNull]OldInstance self, object other) {
  508. return self.CompareForwardReverse(other, "__lt__", "__gt__");
  509. }
  510. [return: MaybeNotImplemented]
  511. public static object operator >=([NotNull]OldInstance self, object other) {
  512. return self.CompareForwardReverse(other, "__ge__", "__le__");
  513. }
  514. [return: MaybeNotImplemented]
  515. public static object operator <=([NotNull]OldInstance self, object other) {
  516. return self.CompareForwardReverse(other, "__le__", "__ge__");
  517. }
  518. private object InternalCompare(string cmp, object other) {
  519. return InvokeOne(this, other, cmp);
  520. }
  521. #region ICustomTypeDescriptor Members
  522. #if !SILVERLIGHT // ICustomTypeDescriptor
  523. AttributeCollection ICustomTypeDescriptor.GetAttributes() {
  524. return CustomTypeDescHelpers.GetAttributes(this);
  525. }
  526. string ICustomTypeDescriptor.GetClassName() {
  527. return CustomTypeDescHelpers.GetClassName(this);
  528. }
  529. string ICustomTypeDescriptor.GetComponentName() {
  530. return CustomTypeDescHelpers.GetComponentName(this);
  531. }
  532. TypeConverter ICustomTypeDescriptor.GetConverter() {
  533. return CustomTypeDescHelpers.GetConverter(this);
  534. }
  535. EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() {
  536. return CustomTypeDescHelpers.GetDefaultEvent(this);
  537. }
  538. PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() {
  539. return CustomTypeDescHelpers.GetDefaultProperty(this);
  540. }
  541. object ICustomTypeDescriptor.GetEditor(Type editorBaseType) {
  542. return CustomTypeDescHelpers.GetEditor(this, editorBaseType);
  543. }
  544. EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) {
  545. return CustomTypeDescHelpers.GetEvents(this, attributes);
  546. }
  547. EventDescriptorCollection ICustomTypeDescriptor.GetEvents() {
  548. return CustomTypeDescHelpers.GetEvents(this);
  549. }
  550. PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) {
  551. return CustomTypeDescHelpers.GetProperties(this, attributes);
  552. }
  553. PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() {
  554. return CustomTypeDescHelpers.GetProperties(this);
  555. }
  556. object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) {
  557. return CustomTypeDescHelpers.GetPropertyOwner(this, pd);
  558. }
  559. #endif
  560. #endregion
  561. #region IWeakReferenceable Members
  562. WeakRefTracker IWeakReferenceable.GetWeakRef() {
  563. return _weakRef;
  564. }
  565. bool IWeakReferenceable.SetWeakRef(WeakRefTracker value) {
  566. _weakRef = value;
  567. return true;
  568. }
  569. void IWeakReferenceable.SetFinalizer(WeakRefTracker value) {
  570. ((IWeakReferenceable)this).SetWeakRef(value);
  571. }
  572. #endregion
  573. #region Rich Equality
  574. // Specific rich equality support for when the user calls directly from oldinstance type.
  575. public int __hash__(CodeContext/*!*/ context) {
  576. object func;
  577. object ret = InvokeOne(this, "__hash__");
  578. if (ret != NotImplementedType.Value) {
  579. if (ret is BigInteger) {
  580. return BigIntegerOps.__hash__((BigInteger)ret);
  581. } else if (!(ret is int))
  582. throw PythonOps.TypeError("expected int from __hash__, got {0}", PythonTypeOps.GetName(ret));
  583. return (int)ret;
  584. }
  585. if (TryGetBoundCustomMember(context, "__cmp__", out func) ||
  586. TryGetBoundCustomMember(context, "__eq__", out func)) {
  587. throw PythonOps.TypeError("unhashable instance");
  588. }
  589. return base.GetHashCode();
  590. }
  591. public override int GetHashCode() {
  592. object ret;
  593. try {
  594. ret = InvokeOne(this, "__hash__");
  595. } catch {
  596. return base.GetHashCode();
  597. }
  598. if (ret != NotImplementedType.Value) {
  599. if (ret is int) {
  600. return (int)ret;
  601. }
  602. if (ret is BigInteger) {
  603. return BigIntegerOps.__hash__((BigInteger)ret);
  604. }
  605. }
  606. return base.GetHashCode();
  607. }
  608. [return: MaybeNotImplemented]
  609. public object __eq__(object other) {
  610. object res = InvokeBoth(other, "__eq__");
  611. if (res != NotImplementedType.Value) {
  612. return res;
  613. }
  614. return NotImplementedType.Value;
  615. }
  616. private object InvokeBoth(object other, string si) {
  617. object res = InvokeOne(this, other, si);
  618. if (res != NotImplementedType.Value) {
  619. return res;
  620. }
  621. OldInstance oi = other as OldInstance;
  622. if (oi != null) {
  623. res = InvokeOne(oi, this, si);
  624. if (res != NotImplementedType.Value) {
  625. return res;
  626. }
  627. }
  628. return NotImplementedType.Value;
  629. }
  630. private static object InvokeOne(OldInstance self, object other, string si) {
  631. object func;
  632. try {
  633. if (!self.TryGetBoundCustomMember(DefaultContext.Default, si, out func)) {
  634. return NotImplementedType.Value;
  635. }
  636. } catch (MissingMemberException) {
  637. return NotImplementedType.Value;
  638. }
  639. return PythonOps.CallWithContext(DefaultContext.Default, func, other);
  640. }
  641. private static object InvokeOne(OldInstance self, object other, object other2, string si) {
  642. object func;
  643. try {
  644. if (!self.TryGetBoundCustomMember(DefaultContext.Default, si, out func)) {
  645. return NotImplementedType.Value;
  646. }
  647. } catch (MissingMemberException) {
  648. return NotImplementedType.Value;
  649. }
  650. return PythonOps.CallWithContext(DefaultContext.Default, func, other, other2);
  651. }
  652. private static object InvokeOne(OldInstance self, string si) {
  653. object func;
  654. try {
  655. if (!self.TryGetBoundCustomMember(DefaultContext.Default, si, out func)) {
  656. return NotImplementedType.Value;
  657. }
  658. } catch (MissingMemberException) {
  659. return NotImplementedType.Value;
  660. }
  661. return PythonOps.CallWithContext(DefaultContext.Default, func);
  662. }
  663. [return: MaybeNotImplemented]
  664. public object __ne__(object other) {
  665. object res = InvokeBoth(other, "__ne__");
  666. if (res != NotImplementedType.Value) {
  667. return res;
  668. }
  669. return NotImplementedType.Value;
  670. }
  671. [return: MaybeNotImplemented]
  672. [SpecialName]
  673. public static object Power([NotNull]OldInstance self, object other, object mod) {
  674. object res = InvokeOne(self, other, mod, "__pow__");
  675. if (res != NotImplementedType.Value) return res;
  676. return NotImplementedType.Value;
  677. }
  678. #endregion
  679. #region ISerializable Members
  680. #if !SILVERLIGHT // SerializationInfo
  681. [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
  682. void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
  683. info.AddValue("__class__", _class);
  684. info.AddValue("__dict__", _dict);
  685. }
  686. #endif
  687. #endregion
  688. #region Private Implementation Details
  689. private void RecurseAttrHierarchyInt(OldClass oc, IDictionary<string, object> attrs) {
  690. foreach (KeyValuePair<object, object> kvp in oc._dict._storage.GetItems()) {
  691. string strKey = kvp.Key as string;
  692. if (strKey != null) {
  693. if (!attrs.ContainsKey(strKey)) {
  694. attrs.Add(strKey, strKey);
  695. }
  696. }
  697. }
  698. // recursively get attrs in parent hierarchy
  699. if (oc.BaseClasses.Count != 0) {
  700. foreach (OldClass parent in oc.BaseClasses) {
  701. RecurseAttrHierarchyInt(parent, attrs);
  702. }
  703. }
  704. }
  705. private void AddFinalizer(CodeContext/*!*/ context) {
  706. InstanceFinalizer oif = new InstanceFinalizer(context, this);
  707. _weakRef = new WeakRefTracker(oif, oif);
  708. }
  709. private void ClearFinalizer() {
  710. if (_weakRef == null) return;
  711. WeakRefTracker wrt = _weakRef;
  712. if (wrt != null) {
  713. // find our handler and remove it (other users could have created weak refs to us)
  714. for (int i = 0; i < wrt.HandlerCount; i++) {
  715. if (wrt.GetHandlerCallback(i) is InstanceFinalizer) {
  716. wrt.RemoveHandlerAt(i);
  717. break;
  718. }
  719. }
  720. // we removed the last handler
  721. if (wrt.HandlerCount == 0) {
  722. GC.SuppressFinalize(wrt);
  723. _weakRef = null;
  724. }
  725. }
  726. }
  727. private bool HasFinalizer() {
  728. if (_weakRef != null) {
  729. WeakRefTracker wrt = _weakRef;
  730. if (wrt != null) {
  731. for (int i = 0; i < wrt.HandlerCount; i++) {
  732. if (wrt.GetHandlerCallback(i) is InstanceFinalizer) {
  733. return true;
  734. }
  735. }
  736. }
  737. }
  738. return false;
  739. }
  740. private bool TryRawGetAttr(CodeContext context, string name, out object ret) {
  741. if (_dict._storage.TryGetValue(name, out ret)) {
  742. return true;
  743. }
  744. if (_class.TryLookupSlot(name, out ret)) {
  745. ret = _class.GetOldStyleDescriptor(context, ret, this, _class);
  746. return true;
  747. }
  748. return false;
  749. }
  750. #endregion
  751. #region IValueEquality Members
  752. #if CLR2
  753. int IValueEquality.GetValueHashCode() {
  754. return GetHashCode();
  755. }
  756. bool IValueEquality.ValueEquals(object other) {
  757. return Equals(other);
  758. }
  759. #endif
  760. #endregion
  761. #region IDynamicMetaObjectProvider Members
  762. DynamicMetaObject/*!*/ IDynamicMetaObjectProvider.GetMetaObject(Expression/*!*/ parameter) {
  763. return new Binding.MetaOldInstance(parameter, BindingRestrictions.Empty, this);
  764. }
  765. #endregion
  766. internal class OldInstanceDebugView {
  767. private readonly OldInstance _userObject;
  768. public OldInstanceDebugView(OldInstance userObject) {
  769. _userObject = userObject;
  770. }
  771. public OldClass __class__ {
  772. get {
  773. return _userObject._class;
  774. }
  775. }
  776. [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
  777. internal List<ObjectDebugView> Members {
  778. get {
  779. var res = new List<ObjectDebugView>();
  780. if (_userObject._dict != null) {
  781. foreach (var v in _userObject._dict) {
  782. res.Add(new ObjectDebugView(v.Key, v.Value));
  783. }
  784. }
  785. return res;
  786. }
  787. }
  788. }
  789. }
  790. }