PageRenderTime 27ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/Method.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 285 lines | 208 code | 55 blank | 22 comment | 34 complexity | dca4dd1efdecc9be6be286f69d85cc76 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.Generic;
  22. using System.Runtime.CompilerServices;
  23. using System.Dynamic;
  24. using Microsoft.Scripting;
  25. using Microsoft.Scripting.Runtime;
  26. using IronPython.Runtime.Operations;
  27. using IronPython.Runtime.Types;
  28. namespace IronPython.Runtime {
  29. [PythonType("instancemethod"), DontMapGetMemberNamesToDir]
  30. public sealed partial class Method : PythonTypeSlot, IWeakReferenceable, IPythonMembersList, IDynamicMetaObjectProvider, ICodeFormattable {
  31. private readonly object _func;
  32. private readonly object _inst;
  33. private readonly object _declaringClass;
  34. private WeakRefTracker _weakref;
  35. public Method(object function, object instance, object @class) {
  36. _func = function;
  37. _inst = instance;
  38. _declaringClass = @class;
  39. }
  40. public Method(object function, object instance) {
  41. if (instance == null) {
  42. throw PythonOps.TypeError("unbound methods must have a class provided");
  43. }
  44. _func = function;
  45. _inst = instance;
  46. }
  47. internal string Name {
  48. get { return (string)PythonOps.GetBoundAttr(DefaultContext.Default, _func, "__name__"); }
  49. }
  50. public string __doc__ {
  51. get {
  52. return PythonOps.GetBoundAttr(DefaultContext.Default, _func, "__doc__") as string;
  53. }
  54. }
  55. public object im_func {
  56. get {
  57. return _func;
  58. }
  59. }
  60. public object __func__ {
  61. get {
  62. return _func;
  63. }
  64. }
  65. public object im_self {
  66. get {
  67. return _inst;
  68. }
  69. }
  70. public object __self__ {
  71. get {
  72. return _inst;
  73. }
  74. }
  75. public object im_class {
  76. get {
  77. // we could have an OldClass (or any other object) here if the user called the ctor directly
  78. return PythonOps.ToPythonType(_declaringClass as PythonType) ?? _declaringClass;
  79. }
  80. }
  81. [SpecialName]
  82. public object Call(CodeContext/*!*/ context, params object[] args) {
  83. return PythonContext.GetContext(context).CallSplat(this, args);
  84. }
  85. [SpecialName]
  86. public object Call(CodeContext/*!*/ context, [ParamDictionary]IDictionary<object, object> kwArgs, params object[] args) {
  87. return PythonContext.GetContext(context).CallWithKeywords(this, args, kwArgs);
  88. }
  89. private Exception BadSelf(object got) {
  90. OldClass dt = im_class as OldClass;
  91. string firstArg;
  92. if (got == null) {
  93. firstArg = "nothing";
  94. } else {
  95. firstArg = PythonOps.GetPythonTypeName(got) + " instance";
  96. }
  97. PythonType pt = im_class as PythonType;
  98. return PythonOps.TypeError("unbound method {0}() must be called with {1} instance as first argument (got {2} instead)",
  99. Name,
  100. (dt != null) ? dt.Name : (pt != null) ? pt.Name : im_class,
  101. firstArg);
  102. }
  103. /// <summary>
  104. /// Validates that the current self object is usable for this method.
  105. /// </summary>
  106. internal object CheckSelf(CodeContext context, object self) {
  107. if (!PythonOps.IsInstance(context, self, im_class)) {
  108. throw BadSelf(self);
  109. }
  110. return self;
  111. }
  112. #region Object Overrides
  113. private string DeclaringClassAsString() {
  114. if (im_class == null) return "?";
  115. PythonType dt = im_class as PythonType;
  116. if (dt != null) return dt.Name;
  117. OldClass oc = im_class as OldClass;
  118. if (oc != null) return oc.Name;
  119. return im_class.ToString();
  120. }
  121. public override bool Equals(object obj) {
  122. Method other = obj as Method;
  123. if (other == null) return false;
  124. return
  125. PythonOps.EqualRetBool(_inst, other._inst) &&
  126. PythonOps.EqualRetBool(_func, other._func);
  127. }
  128. public override int GetHashCode() {
  129. if (_inst == null) return PythonOps.Hash(DefaultContext.Default, _func);
  130. return PythonOps.Hash(DefaultContext.Default, _inst) ^ PythonOps.Hash(DefaultContext.Default, _func);
  131. }
  132. #endregion
  133. #region IWeakReferenceable Members
  134. WeakRefTracker IWeakReferenceable.GetWeakRef() {
  135. return _weakref;
  136. }
  137. bool IWeakReferenceable.SetWeakRef(WeakRefTracker value) {
  138. _weakref = value;
  139. return true;
  140. }
  141. void IWeakReferenceable.SetFinalizer(WeakRefTracker value) {
  142. ((IWeakReferenceable)this).SetWeakRef(value);
  143. }
  144. #endregion
  145. #region Custom member access
  146. [SpecialName]
  147. public object GetCustomMember(CodeContext context, string name) {
  148. switch (name) {
  149. // Get the module name from the function and pass that out. Note that CPython's method has
  150. // no __module__ attribute and this value can be gotten via a call to method.__getattribute__
  151. // there as well.
  152. case "__module__":
  153. return PythonOps.GetBoundAttr(context, _func, "__module__");
  154. case "__name__":
  155. return PythonOps.GetBoundAttr(DefaultContext.Default, _func, "__name__");
  156. default:
  157. object value;
  158. string symbol = name;
  159. if (TypeCache.Method.TryGetBoundMember(context, this, symbol, out value) || // look on method
  160. PythonOps.TryGetBoundAttr(context, _func, symbol, out value)) { // Forward to the func
  161. return value;
  162. }
  163. return OperationFailed.Value;
  164. }
  165. }
  166. [SpecialName]
  167. public void SetMemberAfter(CodeContext context, string name, object value) {
  168. TypeCache.Method.SetMember(context, this, name, value);
  169. }
  170. [SpecialName]
  171. public void DeleteMember(CodeContext context, string name) {
  172. TypeCache.Method.DeleteMember(context, this, name);
  173. }
  174. IList<string> IMembersList.GetMemberNames() {
  175. return PythonOps.GetStringMemberList(this);
  176. }
  177. IList<object> IPythonMembersList.GetMemberNames(CodeContext/*!*/ context) {
  178. List ret = TypeCache.Method.GetMemberNames(context);
  179. ret.AddNoLockNoDups("__module__");
  180. PythonFunction pf = _func as PythonFunction;
  181. if (pf != null) {
  182. PythonDictionary dict = pf.func_dict;
  183. // Check the func
  184. foreach (KeyValuePair<object, object> kvp in dict) {
  185. ret.AddNoLockNoDups(kvp.Key);
  186. }
  187. }
  188. return ret;
  189. }
  190. #endregion
  191. #region PythonTypeSlot Overrides
  192. internal override bool TryGetValue(CodeContext context, object instance, PythonType owner, out object value) {
  193. if (this.im_self == null) {
  194. if (owner == null || owner == im_class || PythonOps.IsSubClass(context, owner, im_class)) {
  195. value = new Method(_func, instance, owner);
  196. return true;
  197. }
  198. }
  199. value = this;
  200. return true;
  201. }
  202. internal override bool GetAlwaysSucceeds {
  203. get {
  204. return true;
  205. }
  206. }
  207. #endregion
  208. #region ICodeFormattable Members
  209. public string/*!*/ __repr__(CodeContext/*!*/ context) {
  210. object name;
  211. if (!PythonOps.TryGetBoundAttr(context, _func, "__name__", out name)) {
  212. name = "?";
  213. }
  214. if (_inst != null) {
  215. return string.Format("<bound method {0}.{1} of {2}>",
  216. DeclaringClassAsString(),
  217. name,
  218. PythonOps.Repr(context, _inst));
  219. } else {
  220. return string.Format("<unbound method {0}.{1}>", DeclaringClassAsString(), name);
  221. }
  222. }
  223. #endregion
  224. #region IDynamicMetaObjectProvider Members
  225. DynamicMetaObject/*!*/ IDynamicMetaObjectProvider.GetMetaObject(Expression/*!*/ parameter) {
  226. return new Binding.MetaMethod(parameter, BindingRestrictions.Empty, this);
  227. }
  228. #endregion
  229. }
  230. }