PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

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

https://bitbucket.org/williamybs/uidipythontool
C# | 2086 lines | 1424 code | 311 blank | 351 comment | 479 complexity | 7dafa1e41cc2f69ca71e4c7ae768420c MD5 | raw file

Large files files are truncated, but you can click here to view the full 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. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using System.Reflection;
  20. using System.Dynamic;
  21. using System.Threading;
  22. using Microsoft.Scripting;
  23. using Microsoft.Scripting.Actions;
  24. using Microsoft.Scripting.Generation;
  25. using Microsoft.Scripting.Runtime;
  26. using Microsoft.Scripting.Utils;
  27. using IronPython.Runtime.Binding;
  28. using IronPython.Runtime.Exceptions;
  29. using IronPython.Runtime.Operations;
  30. #if CLR2
  31. using Microsoft.Scripting.Math;
  32. using Complex = Microsoft.Scripting.Math.Complex64;
  33. #else
  34. using System.Numerics;
  35. #endif
  36. namespace IronPython.Runtime.Types {
  37. /// <summary>
  38. /// Helpers for interacting w/ .NET types. This includes:
  39. ///
  40. /// Member resolution via GetMember/GetMembers. This performs a member lookup which includes the registered
  41. /// extension types in the PythonBinder. Internally the class has many MemberResolver's which provide
  42. /// the various resolution behaviors.
  43. ///
  44. /// Cached member access - this is via static classes such as Object and provides various MemberInfo's so we're
  45. /// not constantly looking up via reflection.
  46. /// </summary>
  47. internal static partial class TypeInfo {
  48. /// <summary> list of resolvers which we run to resolve items </summary>
  49. private static readonly MemberResolver/*!*/[]/*!*/ _resolvers = MakeResolverTable();
  50. [MultiRuntimeAware]
  51. private static DocumentationDescriptor _docDescr;
  52. [MultiRuntimeAware]
  53. internal static Dictionary<string, PythonOperationKind> _pythonOperatorTable;
  54. #region Public member resolution
  55. /// <summary>
  56. /// Gets the statically known member from the type with the specific name. Searches the entire type hierarchy to find the specified member.
  57. /// </summary>
  58. public static MemberGroup/*!*/ GetMemberAll(PythonBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  59. Assert.NotNull(binder, action, type, name);
  60. PerfTrack.NoteEvent(PerfTrack.Categories.ReflectedTypes, String.Format("ResolveMember: {0} {1}", type.Name, name));
  61. return GetMemberGroup(new ResolveBinder(binder), action, type, name);
  62. }
  63. /// <summary>
  64. /// Gets all the statically known members from the specified type. Searches the entire type hierarchy to get all possible members.
  65. ///
  66. /// The result may include multiple resolution. It is the callers responsibility to only treat the 1st one by name as existing.
  67. /// </summary>
  68. public static IList<ResolvedMember/*!*/>/*!*/ GetMembersAll(PythonBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  69. Assert.NotNull(binder, action, type);
  70. return GetResolvedMembers(new ResolveBinder(binder), action, type);
  71. }
  72. /// <summary>
  73. /// Gets the statically known member from the type with the specific name. Searches only the specified type to find the member.
  74. /// </summary>
  75. public static MemberGroup/*!*/ GetMember(PythonBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  76. Assert.NotNull(binder, action, type, name);
  77. PerfTrack.NoteEvent(PerfTrack.Categories.ReflectedTypes, String.Format("LookupMember: {0} {1}", type.Name, name));
  78. return GetMemberGroup(new LookupBinder(binder), action, type, name);
  79. }
  80. /// <summary>
  81. /// Gets all the statically known members from the specified type. Searches only the specified type to find the members.
  82. ///
  83. /// The result may include multiple resolution. It is the callers responsibility to only treat the 1st one by name as existing.
  84. /// </summary>
  85. public static IList<ResolvedMember/*!*/>/*!*/ GetMembers(PythonBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  86. Assert.NotNull(binder, action, type);
  87. return GetResolvedMembers(new LookupBinder(binder), action, type);
  88. }
  89. #endregion
  90. #region Cached type members
  91. public static class _Object {
  92. public new static readonly MethodInfo/*!*/ GetType = typeof(object).GetMethod("GetType");
  93. }
  94. public static class _IPythonObject {
  95. public static readonly PropertyInfo/*!*/ PythonType = typeof(IPythonObject).GetProperty("PythonType");
  96. public static readonly PropertyInfo/*!*/ Dict = typeof(IPythonObject).GetProperty("Dict");
  97. }
  98. public static class _PythonOps {
  99. public static readonly MethodInfo/*!*/ SlotTryGetBoundValue = typeof(PythonOps).GetMethod("SlotTryGetBoundValue");
  100. public static readonly MethodInfo/*!*/ GetTypeVersion = typeof(PythonOps).GetMethod("GetTypeVersion");
  101. public static readonly MethodInfo/*!*/ CheckTypeVersion = typeof(PythonOps).GetMethod("CheckTypeVersion");
  102. }
  103. public static class _OperationFailed {
  104. public static readonly FieldInfo/*!*/ Value = typeof(OperationFailed).GetField("Value");
  105. }
  106. public static class _PythonDictionary {
  107. public static readonly MethodInfo/*!*/ TryGetvalue = typeof(PythonDictionary).GetMethod("TryGetValue");
  108. }
  109. public static class _PythonGenerator {
  110. public static readonly ConstructorInfo Ctor = typeof(PythonGenerator).GetConstructor(new Type[] { typeof(PythonFunction) });
  111. }
  112. #endregion
  113. #region MemberResolver implementations and infrastructure
  114. /// <summary>
  115. /// Abstract class used for resolving members. This provides two methods of member look. The first is looking
  116. /// up a single member by name. The other is getting all of the members.
  117. ///
  118. /// There are various subclasses of this which have different methods of resolving the members. The primary
  119. /// function of the resolvers are to provide the name->value lookup. They also need to provide a simple name
  120. /// enumerator. The enumerator is kept simple because it's allowed to return duplicate names as well as return
  121. /// names of members that don't exist. The base MemberResolver will then verify their existance as well as
  122. /// filter duplicates.
  123. /// </summary>
  124. abstract class MemberResolver {
  125. /// <summary>
  126. /// Looks up an individual member and returns a MemberGroup with the given members.
  127. /// </summary>
  128. public abstract MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name);
  129. /// <summary>
  130. /// Returns a list of members that exist on the type. The ResolvedMember structure indicates both
  131. /// the name and provides the MemberGroup.
  132. /// </summary>
  133. public IList<ResolvedMember/*!*/>/*!*/ ResolveMembers(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  134. Dictionary<string, ResolvedMember> members = new Dictionary<string, ResolvedMember>();
  135. foreach (string name in GetCandidateNames(binder, action, type)) {
  136. if (members.ContainsKey(name)) {
  137. continue;
  138. }
  139. MemberGroup member = ResolveMember(binder, action, type, name);
  140. if (member.Count > 0) {
  141. members[name] = new ResolvedMember(name, member);
  142. }
  143. }
  144. ResolvedMember[] res = new ResolvedMember[members.Count];
  145. members.Values.CopyTo(res, 0);
  146. return res;
  147. }
  148. /// <summary>
  149. /// Returns a list of possible members which could exist. ResolveMember needs to be called to verify their existance. Duplicate
  150. /// names can also be returned.
  151. /// </summary>
  152. protected abstract IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type);
  153. }
  154. /// <summary>
  155. /// One off resolver for various special methods which are known by name. A delegate is provided to provide the actual member which
  156. /// will be resolved.
  157. /// </summary>
  158. class OneOffResolver : MemberResolver {
  159. private string/*!*/ _name;
  160. private Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ _resolver;
  161. public OneOffResolver(string/*!*/ name, Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ resolver) {
  162. Assert.NotNull(name, resolver);
  163. _name = name;
  164. _resolver = resolver;
  165. }
  166. public override MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  167. Assert.NotNull(binder, action, type, name);
  168. if (name == _name) {
  169. return _resolver(binder, type);
  170. }
  171. return MemberGroup.EmptyGroup;
  172. }
  173. protected override IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  174. yield return _name;
  175. }
  176. }
  177. /// <summary>
  178. /// Standard resolver for looking up .NET members. Uses reflection to get the members by name.
  179. /// </summary>
  180. class StandardResolver : MemberResolver {
  181. public override MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  182. if (name == ".ctor" || name == ".cctor") return MemberGroup.EmptyGroup;
  183. // normal binding
  184. MemberGroup res;
  185. foreach (Type curType in binder.GetContributingTypes(type)) {
  186. res = FilterSpecialNames(binder.GetMember(curType, name), name, action);
  187. if (res.Count > 0) {
  188. return res;
  189. }
  190. }
  191. if (type.IsInterface) {
  192. foreach (Type t in type.GetInterfaces()) {
  193. res = FilterSpecialNames(binder.GetMember(t, name), name, action);
  194. if (res.Count > 0) {
  195. return res;
  196. }
  197. }
  198. }
  199. return MemberGroup.EmptyGroup;
  200. }
  201. protected override IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  202. foreach (Type curType in binder.GetContributingTypes(type)) {
  203. foreach (MemberInfo mi in curType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) {
  204. if (mi.MemberType == MemberTypes.Method) {
  205. MethodInfo meth = (MethodInfo)mi;
  206. if (meth.IsSpecialName) {
  207. if (meth.IsDefined(typeof(PropertyMethodAttribute), true)) {
  208. if (meth.Name.StartsWith("Get") || meth.Name.StartsWith("Set")) {
  209. yield return meth.Name.Substring(3);
  210. } else {
  211. Debug.Assert(meth.Name.StartsWith("Delete"));
  212. yield return meth.Name.Substring(6);
  213. }
  214. }
  215. continue;
  216. }
  217. }
  218. yield return mi.Name;
  219. }
  220. }
  221. }
  222. }
  223. /// <summary>
  224. /// Resolves methods mapped to __eq__ and __ne__ from:
  225. /// 1. IStructuralEquatable.Equals
  226. /// 2. IValueEquality.Equals (CLR2 only)
  227. /// </summary>
  228. class EqualityResolver : MemberResolver {
  229. public static readonly EqualityResolver Instance = new EqualityResolver();
  230. private EqualityResolver() { }
  231. public override MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  232. Assert.NotNull(binder, action, type, name);
  233. bool equality;
  234. switch (name) {
  235. case "__eq__": equality = true; break;
  236. case "__ne__": equality = false; break;
  237. default:
  238. return MemberGroup.EmptyGroup;
  239. }
  240. if (typeof(IStructuralEquatable).IsAssignableFrom(type)) {
  241. return new MemberGroup(
  242. GetEqualityMethods(type, equality ? "StructuralEqualityMethod" : "StructuralInequalityMethod")
  243. );
  244. #if CLR2
  245. } else if (typeof(IValueEquality).IsAssignableFrom(type)) {
  246. return new MemberGroup(
  247. GetEqualityMethods(type, equality ? "ValueEqualsMethod" : "ValueNotEqualsMethod")
  248. );
  249. #endif
  250. }
  251. return MemberGroup.EmptyGroup;
  252. }
  253. protected override IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  254. yield return "__eq__";
  255. yield return "__ne__";
  256. }
  257. }
  258. /// <summary>
  259. /// Resolves methods mapped to __gt__, __lt__, __ge__, __le__, as well as providing an alternate resolution
  260. /// for __eq__ and __ne__, from the comparable type's CompareTo method.
  261. ///
  262. /// This should be run after the EqualityResolver.
  263. /// </summary>
  264. class ComparisonResolver : MemberResolver {
  265. private readonly bool _excludePrimitiveTypes;
  266. private readonly Type/*!*/ _comparable;
  267. private readonly Dictionary<string/*!*/, string/*!*/>/*!*/ _helperMap;
  268. public ComparisonResolver(Type/*!*/ comparable, string/*!*/ helperPrefix) {
  269. Assert.NotNull(comparable, helperPrefix);
  270. _excludePrimitiveTypes = comparable == typeof(IComparable);
  271. _comparable = comparable;
  272. _helperMap = new Dictionary<string, string>();
  273. _helperMap["__eq__"] = helperPrefix + "Equality";
  274. _helperMap["__ne__"] = helperPrefix + "Inequality";
  275. _helperMap["__gt__"] = helperPrefix + "GreaterThan";
  276. _helperMap["__lt__"] = helperPrefix + "LessThan";
  277. _helperMap["__ge__"] = helperPrefix + "GreaterEqual";
  278. _helperMap["__le__"] = helperPrefix + "LessEqual";
  279. }
  280. public override MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  281. Assert.NotNull(binder, action, type, name);
  282. // Do not map IComparable if this is a primitive builtin type.
  283. if (_excludePrimitiveTypes) {
  284. if (type.IsPrimitive || type == typeof(BigInteger) ||
  285. type == typeof(string) || type == typeof(decimal)) {
  286. return MemberGroup.EmptyGroup;
  287. }
  288. }
  289. string helperName;
  290. if (_helperMap.TryGetValue(name, out helperName) &&
  291. _comparable.IsAssignableFrom(type)) {
  292. return new MemberGroup(GetEqualityMethods(type, helperName));
  293. }
  294. return MemberGroup.EmptyGroup;
  295. }
  296. protected override IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  297. return _helperMap.Keys;
  298. }
  299. }
  300. /// <summary>
  301. /// Resolves methods mapped to __*__ methods automatically from the .NET operator.
  302. /// </summary>
  303. class OperatorResolver : MemberResolver {
  304. public override MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  305. if (type.IsSealed && type.IsAbstract) {
  306. // static types don't have PythonOperationKind
  307. return MemberGroup.EmptyGroup;
  308. }
  309. // try mapping __*__ methods to .NET method names
  310. PythonOperationKind opMap;
  311. EnsureOperatorTable();
  312. if (_pythonOperatorTable.TryGetValue(name, out opMap)) {
  313. if (IncludeOperatorMethod(type, opMap)) {
  314. OperatorMapping opInfo;
  315. if (IsReverseOperator(opMap)) {
  316. opInfo = OperatorMapping.GetOperatorMapping(opMap & ~PythonOperationKind.Reversed);
  317. } else {
  318. opInfo = OperatorMapping.GetOperatorMapping(opMap);
  319. }
  320. if (opInfo != null) {
  321. foreach (Type curType in binder.GetContributingTypes(type)) {
  322. #if !CLR2
  323. if (curType == typeof(double)) {
  324. if ((opInfo.Operator & PythonOperationKind.Comparison) != 0) {
  325. // we override these with our own comparisons in DoubleOps
  326. continue;
  327. }
  328. } else
  329. #endif
  330. if (curType == typeof(BigInteger)) {
  331. if (opInfo.Operator == PythonOperationKind.Mod ||
  332. opInfo.Operator == PythonOperationKind.RightShift ||
  333. opInfo.Operator == PythonOperationKind.LeftShift ||
  334. opInfo.Operator == PythonOperationKind.Compare ||
  335. opInfo.Operator == PythonOperationKind.Divide) {
  336. // we override these with our own modulus/power PythonOperationKind which are different from BigInteger.
  337. continue;
  338. }
  339. #if !CLR2
  340. } else if (curType == typeof(Complex) && opInfo.Operator == PythonOperationKind.Divide) {
  341. // we override this with our own division PythonOperationKind which is different from .NET Complex.
  342. continue;
  343. #endif
  344. }
  345. Debug.Assert(opInfo.Name != "Equals");
  346. MemberGroup res = binder.GetMember(curType, opInfo.Name);
  347. if (res.Count == 0 && opInfo.AlternateName != null) {
  348. res = binder.GetMember(curType, opInfo.AlternateName);
  349. if (opInfo.AlternateName == "Equals") {
  350. // "Equals" is available as an alternate method name. Because it's also on object and Python
  351. // doesn't define it on object we need to filter it out.
  352. res = FilterObjectEquality(res);
  353. }
  354. res = FilterAlternateMethods(opInfo, res);
  355. }
  356. if (res.Count > 0) {
  357. return FilterForwardReverseMethods(name, res, type, opMap);
  358. }
  359. }
  360. }
  361. }
  362. }
  363. if (name == "__call__") {
  364. MemberGroup res = binder.GetMember(type, "Call");
  365. if (res.Count > 0) {
  366. return res;
  367. }
  368. }
  369. return MemberGroup.EmptyGroup;
  370. }
  371. /// <summary>
  372. /// Filters alternative methods out that don't match the expected signature and therefore
  373. /// are just sharing a common method name.
  374. /// </summary>
  375. private static MemberGroup FilterAlternateMethods(OperatorMapping opInfo, MemberGroup res) {
  376. if (res.Count > 0 && opInfo.AlternateExpectedType != null) {
  377. List<MemberTracker> matchingMethods = new List<MemberTracker>();
  378. for (int i = 0; i < res.Count; i++) {
  379. MemberTracker mt = res[i];
  380. if (mt.MemberType == TrackerTypes.Method &&
  381. ((MethodTracker)mt).Method.ReturnType == opInfo.AlternateExpectedType) {
  382. matchingMethods.Add(mt);
  383. }
  384. }
  385. if (matchingMethods.Count == 0) {
  386. res = MemberGroup.EmptyGroup;
  387. } else {
  388. res = new MemberGroup(matchingMethods.ToArray());
  389. }
  390. }
  391. return res;
  392. }
  393. /// <summary>
  394. /// Removes Object.Equals methods as we never return these for PythonOperationKind.
  395. /// </summary>
  396. private static MemberGroup/*!*/ FilterObjectEquality(MemberGroup/*!*/ group) {
  397. List<MemberTracker> res = null;
  398. for (int i = 0; i < group.Count; i++) {
  399. MemberTracker mt = group[i];
  400. if (mt.MemberType == TrackerTypes.Method && (mt.DeclaringType == typeof(object) || mt.DeclaringType == typeof(double) || mt.DeclaringType == typeof(float)) && mt.Name == "Equals") {
  401. if (res == null) {
  402. res = new List<MemberTracker>();
  403. for (int j = 0; j < i; j++) {
  404. res.Add(group[j]);
  405. }
  406. }
  407. } else if (mt.MemberType == TrackerTypes.Method && mt.DeclaringType == typeof(ValueType) && mt.Name == "Equals") {
  408. // ValueType.Equals overrides object.Equals but we can't call it w/ a boxed value type therefore
  409. // we return the object version and the virtual call will dispatch to ValueType.Equals.
  410. if (res == null) {
  411. res = new List<MemberTracker>();
  412. for (int j = 0; j < i; j++) {
  413. res.Add(group[j]);
  414. }
  415. }
  416. res.Add(MemberTracker.FromMemberInfo(typeof(object).GetMethod("Equals", new Type[] { typeof(object) })));
  417. } else if (res != null) {
  418. res.Add(group[i]);
  419. }
  420. }
  421. if (res != null) {
  422. if (res.Count == 0) {
  423. return MemberGroup.EmptyGroup;
  424. }
  425. return new MemberGroup(res.ToArray());
  426. }
  427. return group;
  428. }
  429. protected override IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  430. EnsureOperatorTable();
  431. foreach (string si in _pythonOperatorTable.Keys) {
  432. yield return si;
  433. }
  434. yield return "__call__";
  435. }
  436. }
  437. /// <summary>
  438. /// Provides bindings to private members when that global option is enabled.
  439. /// </summary>
  440. class PrivateBindingResolver : MemberResolver {
  441. private const BindingFlags _privateFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
  442. public override MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  443. if (binder.DomainManager.Configuration.PrivateBinding) {
  444. // in private binding mode Python exposes private members under a mangled name.
  445. string header = "_" + type.Name + "__";
  446. if (name.StartsWith(header)) {
  447. string memberName = name.Substring(header.Length);
  448. MemberGroup res = new MemberGroup(type.GetMember(memberName, _privateFlags));
  449. if (res.Count > 0) {
  450. return FilterFieldAndEvent(res);
  451. }
  452. res = new MemberGroup(type.GetMember(memberName, BindingFlags.FlattenHierarchy | _privateFlags));
  453. if (res.Count > 0) {
  454. return FilterFieldAndEvent(res);
  455. }
  456. }
  457. }
  458. return MemberGroup.EmptyGroup;
  459. }
  460. protected override IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  461. if (!binder.DomainManager.Configuration.PrivateBinding) {
  462. yield break;
  463. }
  464. foreach (MemberInfo mi in type.GetMembers(_privateFlags | BindingFlags.FlattenHierarchy)) {
  465. yield return String.Concat("_", mi.DeclaringType.Name, "__", mi.Name);
  466. }
  467. }
  468. }
  469. /// <summary>
  470. /// Provides resolutions for protected members that haven't yet been
  471. /// subclassed by NewTypeMaker.
  472. /// </summary>
  473. class ProtectedMemberResolver : MemberResolver {
  474. public override MemberGroup/*!*/ ResolveMember(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type, string/*!*/ name) {
  475. foreach (Type t in binder.GetContributingTypes(type)) {
  476. MemberGroup res = new MemberGroup(ArrayUtils.FindAll(t.GetMember(name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy), ProtectedOnly));
  477. for (int i = 0; i < res.Count; i++) {
  478. MethodTracker meth = res[i] as MethodTracker;
  479. if (meth == null) {
  480. continue;
  481. }
  482. if (meth.Name == "Finalize" && meth.Method.GetBaseDefinition() == typeof(object).GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance)) {
  483. MemberTracker[] retained = new MemberTracker[res.Count - 1];
  484. if (res.Count == 1) {
  485. res = MemberGroup.EmptyGroup;
  486. } else {
  487. for (int j = 0; j < i; j++) {
  488. retained[j] = res[j];
  489. }
  490. for (int j = i + 1; j < res.Count; j++) {
  491. retained[j - 1] = res[j];
  492. }
  493. res = new MemberGroup(retained);
  494. }
  495. break;
  496. }
  497. }
  498. return FilterSpecialNames(res, name, action);
  499. }
  500. return MemberGroup.EmptyGroup;
  501. }
  502. protected override IEnumerable<string/*!*/>/*!*/ GetCandidateNames(MemberBinder/*!*/ binder, MemberRequestKind/*!*/ action, Type/*!*/ type) {
  503. // these members are visible but only accept derived types.
  504. foreach (Type t in binder.GetContributingTypes(type)) {
  505. MemberInfo[] mems = ArrayUtils.FindAll(t.GetMembers(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic), ProtectedOnly);
  506. foreach (MemberInfo mi in mems) {
  507. yield return mi.Name;
  508. }
  509. }
  510. }
  511. }
  512. /// <summary>
  513. /// Creates the resolver table which includes all the possible resolutions.
  514. /// </summary>
  515. /// <returns></returns>
  516. private static MemberResolver/*!*/[]/*!*/ MakeResolverTable() {
  517. return new MemberResolver[] {
  518. // values that live on object need to run before the StandardResolver
  519. // which will pick up values off of object.
  520. new OneOffResolver("__str__", StringResolver),
  521. new OneOffResolver("__new__", NewResolver),
  522. new OneOffResolver("__repr__", ReprResolver),
  523. new OneOffResolver("__hash__", HashResolver),
  524. new OneOffResolver("__iter__", IterResolver),
  525. #if !SILVERLIGHT
  526. new OneOffResolver("__reduce_ex__", SerializationResolver),
  527. #endif
  528. // The standard resolver looks for types using .NET reflection by name
  529. new StandardResolver(),
  530. // Runs after StandardResolver so custom __eq__ methods can be added
  531. // that support things like returning NotImplemented vs. IValueEquality
  532. // which only supports true/false. Runs before OperatorResolver so that
  533. // IStructuralEquatable and IValueEquality take precedence over Equals,
  534. // which can be provided for nice .NET interop.
  535. EqualityResolver.Instance,
  536. new ComparisonResolver(typeof(IStructuralComparable), "StructuralComparable"),
  537. new OneOffResolver("__all__", AllResolver),
  538. new OneOffResolver("__contains__", ContainsResolver),
  539. new OneOffResolver("__dir__", DirResolver),
  540. new OneOffResolver("__doc__", DocResolver),
  541. new OneOffResolver("__enter__", EnterResolver),
  542. new OneOffResolver("__exit__", ExitResolver),
  543. new OneOffResolver("__len__", LengthResolver),
  544. new OneOffResolver("__format__", FormatResolver),
  545. new OneOffResolver("next", NextResolver),
  546. new OneOffResolver("__complex__", ComplexResolver),
  547. new OneOffResolver("__float__", FloatResolver),
  548. new OneOffResolver("__int__", IntResolver),
  549. new OneOffResolver("__long__", BigIntegerResolver),
  550. // non standard PythonOperationKind which are Python specific
  551. new OneOffResolver("__truediv__", new OneOffOperatorBinder("TrueDivide", "__truediv__", PythonOperationKind.TrueDivide).Resolver),
  552. new OneOffResolver("__rtruediv__", new OneOffOperatorBinder("TrueDivide", "__rtruediv__", PythonOperationKind.ReverseTrueDivide).Resolver),
  553. new OneOffResolver("__itruediv__", new OneOffOperatorBinder("InPlaceTrueDivide", "__itruediv__", PythonOperationKind.InPlaceTrueDivide).Resolver),
  554. new OneOffResolver("__floordiv__", new OneOffOperatorBinder("FloorDivide", "__floordiv__", PythonOperationKind.FloorDivide).Resolver),
  555. new OneOffResolver("__rfloordiv__", new OneOffOperatorBinder("FloorDivide", "__rfloordiv__", PythonOperationKind.ReverseFloorDivide).Resolver),
  556. new OneOffResolver("__ifloordiv__", new OneOffOperatorBinder("InPlaceFloorDivide", "__ifloordiv__", PythonOperationKind.InPlaceFloorDivide).Resolver),
  557. new OneOffResolver("__pow__", new OneOffPowerBinder("__pow__", PythonOperationKind.Power).Resolver),
  558. new OneOffResolver("__rpow__", new OneOffPowerBinder("__rpow__", PythonOperationKind.ReversePower).Resolver),
  559. new OneOffResolver("__ipow__", new OneOffOperatorBinder("InPlacePower", "__ipow__", PythonOperationKind.InPlacePower).Resolver),
  560. new OneOffResolver("__abs__", new OneOffOperatorBinder("Abs", "__abs__", PythonOperationKind.AbsoluteValue).Resolver),
  561. new OneOffResolver("__divmod__", new OneOffOperatorBinder("DivMod", "__divmod__", PythonOperationKind.DivMod).Resolver),
  562. new OneOffResolver("__rdivmod__", new OneOffOperatorBinder("DivMod", "__rdivmod__", PythonOperationKind.DivMod).Resolver),
  563. // The operator resolver maps standard .NET operator methods into Python operator
  564. // methods
  565. new OperatorResolver(),
  566. // Runs after operator resolver to map default members to __getitem__/__setitem__
  567. new OneOffResolver("__getitem__", GetItemResolver),
  568. new OneOffResolver("__setitem__", SetItemResolver),
  569. // Runs after operator resolver to map __ne__ -> !__eq__
  570. new OneOffResolver("__ne__", FallbackInequalityResolver),
  571. // Runs after the operator resolver to map IComparable
  572. new ComparisonResolver(typeof(IComparable), "Comparable"),
  573. // Protected members are visible but only usable from derived types
  574. new ProtectedMemberResolver(),
  575. // Support binding to private members if the user has enabled that feature
  576. new PrivateBindingResolver(),
  577. };
  578. }
  579. #endregion
  580. #region One-off resolvers
  581. #region Resolving numerical conversions (__complex__, __float__, __int__, and __long__)
  582. /// <summary>
  583. /// Provides a resolution for __complex__
  584. /// </summary>
  585. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ ComplexResolver {
  586. get {
  587. if (_ComplexResolver != null) return _ComplexResolver;
  588. _ComplexResolver = MakeConversionResolver(new List<Type> {
  589. typeof(Complex), typeof(ExtensibleComplex), typeof(Extensible<Complex>),
  590. typeof(double), typeof(Extensible<double>)
  591. });
  592. return _ComplexResolver;
  593. }
  594. }
  595. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/> _ComplexResolver;
  596. /// <summary>
  597. /// Provides a resolution for __float__
  598. /// </summary>
  599. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ FloatResolver {
  600. get {
  601. if (_FloatResolver != null) return _FloatResolver;
  602. _FloatResolver = MakeConversionResolver(new List<Type> {
  603. typeof(double), typeof(Extensible<double>)
  604. });
  605. return _FloatResolver;
  606. }
  607. }
  608. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/> _FloatResolver;
  609. /// <summary>
  610. /// Provides a resolution for __int__
  611. /// </summary>
  612. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ IntResolver {
  613. get {
  614. if (_IntResolver != null) return _IntResolver;
  615. _IntResolver = MakeConversionResolver(new List<Type> {
  616. typeof(int), typeof(Extensible<int>),
  617. typeof(BigInteger), typeof(Extensible<BigInteger>)
  618. });
  619. return _IntResolver;
  620. }
  621. }
  622. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/> _IntResolver;
  623. /// <summary>
  624. /// Provides a resolution for __long__
  625. /// </summary>
  626. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ BigIntegerResolver {
  627. get {
  628. if (_BigIntegerResolver != null) return _BigIntegerResolver;
  629. _BigIntegerResolver = MakeConversionResolver(new List<Type> {
  630. typeof(BigInteger), typeof(Extensible<BigInteger>),
  631. typeof(int), typeof(Extensible<int>)
  632. });
  633. return _BigIntegerResolver;
  634. }
  635. }
  636. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/> _BigIntegerResolver;
  637. /// <summary>
  638. /// Provides a resolution for __getitem__
  639. /// </summary>
  640. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ GetItemResolver {
  641. get {
  642. if (_GetItemResolver == null) {
  643. _GetItemResolver = MakeIndexerResolver(false);
  644. }
  645. return _GetItemResolver;
  646. }
  647. }
  648. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/> _GetItemResolver;
  649. /// <summary>
  650. /// Provides a resolution for __setitem__
  651. /// </summary>
  652. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/>/*!*/ SetItemResolver {
  653. get {
  654. if (_SetItemResolver == null) {
  655. _SetItemResolver = MakeIndexerResolver(true);
  656. }
  657. return _SetItemResolver;
  658. }
  659. }
  660. private static Func<MemberBinder/*!*/, Type/*!*/, MemberGroup/*!*/> _SetItemResolver;
  661. #endregion
  662. /// <summary>
  663. /// Provides a resolution for __str__.
  664. /// </summary>
  665. private static MemberGroup/*!*/ StringResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  666. if (type != typeof(double) && type != typeof(float)
  667. #if !CLR2
  668. && type != typeof(Complex)
  669. #endif
  670. ) {
  671. MethodInfo tostr = type.GetMethod("ToString", Type.EmptyTypes);
  672. if (tostr != null && tostr.DeclaringType != typeof(object)) {
  673. return GetInstanceOpsMethod(type, "ToStringMethod");
  674. }
  675. }
  676. return MemberGroup.EmptyGroup;
  677. }
  678. /// <summary>
  679. /// Provides a resolution for __repr__
  680. /// </summary>
  681. private static MemberGroup/*!*/ ReprResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  682. // __repr__ for normal .NET types is special, if we're a Python type then
  683. // we'll use one of the built-in reprs (from object or from the type)
  684. if (!PythonBinder.IsPythonType(type) &&
  685. (!type.IsSealed || !type.IsAbstract)) { // static types don't get __repr__
  686. // check and see if __repr__ has been overridden by the base type.
  687. foreach (Type t in binder.GetContributingTypes(type)) {
  688. if (t == typeof(ObjectOps) && type != typeof(object)) {
  689. break;
  690. }
  691. if (t.GetMember("__repr__").Length > 0) {
  692. // type has a specific __repr__ overload, pick it up normally later
  693. return MemberGroup.EmptyGroup;
  694. }
  695. }
  696. // no override, pick up the default fancy .NET __repr__
  697. return binder.GetBaseInstanceMethod(type, "FancyRepr");
  698. }
  699. return MemberGroup.EmptyGroup;
  700. }
  701. #if !SILVERLIGHT
  702. private static MemberGroup/*!*/ SerializationResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  703. if (type.IsSerializable && !PythonBinder.IsPythonType(type)) {
  704. string methodName = "__reduce_ex__";
  705. if (!TypeOverridesMethod(binder, type, methodName)) {
  706. return GetInstanceOpsMethod(type, "SerializeReduce");
  707. }
  708. }
  709. return MemberGroup.EmptyGroup;
  710. }
  711. /// <summary>
  712. /// Helper to see if the type explicitly overrides the method. This ignores members
  713. /// defined on object.
  714. /// </summary>
  715. private static bool TypeOverridesMethod(MemberBinder/*!*/ binder, Type/*!*/ type, string/*!*/ methodName) {
  716. // check and see if the method has been overridden by the base type.
  717. foreach (Type t in binder.GetContributingTypes(type)) {
  718. if (!PythonBinder.IsPythonType(type) && t == typeof(ObjectOps) && type != typeof(object)) {
  719. break;
  720. }
  721. MemberInfo[] reduce = t.GetMember(methodName);
  722. if (reduce.Length > 0) {
  723. // type has a specific overload
  724. return true;
  725. }
  726. }
  727. return false;
  728. }
  729. #endif
  730. /// <summary>
  731. /// Provides a resolution for __hash__, first looking for IStructuralEquatable.GetHashCode,
  732. /// then IValueEquality.GetValueHashCode.
  733. /// </summary>
  734. private static MemberGroup/*!*/ HashResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  735. #if CLR2
  736. if ((typeof(IStructuralEquatable).IsAssignableFrom(type) ||
  737. typeof(IValueEquality).IsAssignableFrom(type)) && !type.IsInterface) {
  738. #else
  739. if (typeof(IStructuralEquatable).IsAssignableFrom(type) && !type.IsInterface) {
  740. #endif
  741. // check and see if __hash__ has been overridden by the base type.
  742. foreach (Type t in binder.GetContributingTypes(type)) {
  743. // if it's defined on object, it's not overridden
  744. if (t == typeof(ObjectOps) || t == typeof(object)) {
  745. break;
  746. }
  747. MemberInfo[] hash = t.GetMember("__hash__");
  748. if (hash.Length > 0) {
  749. return MemberGroup.EmptyGroup;
  750. }
  751. }
  752. #if CLR2
  753. if (typeof(IStructuralEquatable).IsAssignableFrom(type)) {
  754. return GetInstanceOpsMethod(type, "StructuralHashMethod");
  755. }
  756. if (typeof(IValueEquality).IsAssignableFrom(type)) {
  757. return new MemberGroup(typeof(IValueEquality).GetMethod("GetValueHashCode"));
  758. }
  759. #else
  760. return GetInstanceOpsMethod(type, "StructuralHashMethod");
  761. #endif
  762. }
  763. // otherwise we'll pick up __hash__ from ObjectOps which will call .NET's .GetHashCode therefore
  764. // we don't explicitly search to see if the object overrides GetHashCode here.
  765. return MemberGroup.EmptyGroup;
  766. }
  767. /// <summary>
  768. /// Provides a resolution for __new__. For standard .NET types __new__ resolves to their
  769. /// constructor. For Python types they inherit __new__ from their base class.
  770. ///
  771. /// TODO: Can we just always fallback to object.__new__? If not why not?
  772. /// </summary>
  773. private static MemberGroup/*!*/ NewResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  774. if (type.IsSealed && type.IsAbstract) {
  775. // static types don't have __new__
  776. return MemberGroup.EmptyGroup;
  777. }
  778. bool isPythonType = typeof(IPythonObject).IsAssignableFrom(type);
  779. // check and see if __new__ has been overridden by the base type.
  780. foreach (Type t in binder.GetContributingTypes(type)) {
  781. if (!isPythonType && t == typeof(ObjectOps) && type != typeof(object)) {
  782. break;
  783. }
  784. MemberInfo[] news = t.GetMember("__new__");
  785. if (news.Length > 0) {
  786. // type has a specific __new__ overload, return that for the constructor
  787. return GetExtensionMemberGroup(type, news);
  788. }
  789. }
  790. // type has no Python __new__, just return the .NET constructors if they have
  791. // a custom new
  792. ConstructorInfo[] ctors = type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);// CompilerHelpers.GetConstructors(type, binder.DomainManager.Configuration.PrivateBinding, true);
  793. ctors = CompilerHelpers.FilterConstructorsToPublicAndProtected(ctors);
  794. if (!PythonTypeOps.IsDefaultNew(ctors)) {
  795. return new MemberGroup(ctors);
  796. }
  797. // if no ctor w/ parameters are defined, fall back to object.__new__ which
  798. // will ignore all the extra arguments allowing the user to just override
  799. // __init__.
  800. return MemberGroup.EmptyGroup;
  801. }
  802. internal static MemberGroup GetExtensionMemberGroup(Type type, MemberInfo[] news) {
  803. List<MemberTracker> mts = new List<MemberTracker>();
  804. foreach (MemberInfo mi in news) {
  805. if (mi.MemberType == MemberTypes.Method) {
  806. if (mi.DeclaringType.IsAssignableFrom(type)) {
  807. mts.Add(MethodTracker.FromMemberInfo(mi));
  808. } else {
  809. mts.Add(MethodTracker.FromMemberInfo(mi, type));
  810. }
  811. }
  812. }
  813. return new MemberGroup(mts.ToArray());
  814. }
  815. /// <summary>
  816. /// Provides a resolution for next
  817. /// </summary>
  818. private static MemberGroup/*!*/ NextResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  819. if (typeof(IEnumerator).IsAssignableFrom(type)) {
  820. return GetInstanceOpsMethod(type, "NextMethod");
  821. }
  822. return MemberGroup.EmptyGroup;
  823. }
  824. /// <summary>
  825. /// Provides a resolution for __len__
  826. /// </summary>
  827. private static MemberGroup/*!*/ LengthResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  828. if (!type.IsDefined(typeof(DontMapICollectionToLenAttribute), true)) {
  829. if (binder.GetInterfaces(type).Contains(typeof(ICollection))) {
  830. return GetInstanceOpsMethod(type, "LengthMethod");
  831. }
  832. foreach (Type t in binder.GetInterfaces(type)) {
  833. if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection<>)) {
  834. MethodInfo genMeth = typeof(InstanceOps).GetMethod("GenericLengthMethod");
  835. return new MemberGroup(
  836. MethodTracker.FromMemberInfo(genMeth.MakeGenericMethod(t.GetGenericArguments()), type)
  837. );
  838. }
  839. }
  840. }
  841. return MemberGroup.EmptyGroup;
  842. }
  843. /// <summary>
  844. /// Provides a resolution for __iter__
  845. /// </summary>
  846. private static MemberGroup/*!*/ IterResolver(MemberBinder/*!*/ binder, Type/*!*/ type) {
  847. if (type == typeof(string)) {
  848. // __iter__ is only exposed in 3.0
  849. if (binder.Binder.Context.PythonOptions.Python30) {
  850. return GetInstanceOpsMethod(type, "IterMethodForString");
  851. }
  852. return MemberGroup.EmptyGroup;
  853. }
  854. if (typeof(Bytes).IsAssignableFrom(type)) {
  855. // __iter__ is only exposed in 3.0
  856. if (binder.Binder.Context.PythonOptions.Python30) {
  857. return GetInstanceOpsMethod(type, "IterMethodForBytes");
  858. }
  859. return MemberGroup.EmptyGroup;
  860. }
  861. foreach (Type t in binder.GetContributingTypes(type)) {
  862. MemberInfo[] news = t.GetMember("__iter__");
  863. if (news.Length > 0) {
  864. // type has a specific __iter__ overload, we'll pick it up later
  865. return MemberGroup.EmptyGroup;
  866. }
  867. }
  868. if (!type.IsDefined(typeof(DontMapIEnumerableToIterAttribute), true)) {
  869. // no special __iter__, use the default.
  870. if (typeof(IEnumerable<>).IsAssignableFrom(type)) {
  871. return GetInstanceOpsMethod(type, "IterMethodForGenericEnumerable");
  872. } else if (typeof(IEnumerable).IsAssignableFrom(type)) {
  873. return GetInstanceOpsMe

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