PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/williamybs/uidipythontool
C# | 175 lines | 118 code | 31 blank | 26 comment | 19 complexity | c91ce01c0332c8b20ec172b3d720fac8 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. using System;
  16. using System.Collections.Generic;
  17. using System.Reflection;
  18. using System.Threading;
  19. using Microsoft.Scripting.Runtime;
  20. using IronPython.Runtime.Operations;
  21. namespace IronPython.Runtime.Types {
  22. // Used to map signatures to specific targets on the embedded reflected method.
  23. public class BuiltinFunctionOverloadMapper : ICodeFormattable {
  24. private BuiltinFunction _function;
  25. private object _instance;
  26. private PythonTuple _allOverloads; // overloads are stored here and may be bound to an instance
  27. public BuiltinFunctionOverloadMapper(BuiltinFunction builtinFunction, object instance) {
  28. this._function = builtinFunction;
  29. this._instance = instance;
  30. }
  31. public object this[params Type[] types] {
  32. get {
  33. return GetOverload(types, Targets);
  34. }
  35. }
  36. protected object GetOverload(Type[] sig, IList<MethodBase> targets) {
  37. return GetOverload(sig, targets, true);
  38. }
  39. private object GetOverload(Type[] sig, IList<MethodBase> targets, bool wrapCtors) {
  40. // We can still end up with more than one target since generic and non-generic
  41. // methods can share the same name and signature. So we'll build up a new
  42. // reflected method with all the candidate targets. A caller can then index this
  43. // reflected method if necessary in order to provide generic type arguments and
  44. // fully disambiguate the target.
  45. // Search for targets with the right number of arguments.
  46. BuiltinFunction bf;
  47. BuiltinFunction.TypeList tl = new BuiltinFunction.TypeList(sig);
  48. lock (_function.OverloadDictionary) {
  49. if (!_function.OverloadDictionary.TryGetValue(tl, out bf)) {
  50. MethodBase[] newTargets = FindMatchingTargets(sig, targets);
  51. if (targets == null)
  52. throw ScriptingRuntimeHelpers.SimpleTypeError(String.Format("No match found for the method signature {0}", sig)); // TODO: Sig to usable display
  53. _function.OverloadDictionary[tl] = bf = new BuiltinFunction(_function.Name, newTargets, Function.DeclaringType, _function.FunctionType);
  54. }
  55. }
  56. if (_instance != null) {
  57. return bf.BindToInstance(_instance);
  58. } else if (wrapCtors) {
  59. return GetTargetFunction(bf);
  60. } else {
  61. return bf;
  62. }
  63. }
  64. private static MethodBase[] FindMatchingTargets(Type[] sig, IList<MethodBase> targets) {
  65. int args = sig.Length;
  66. List<MethodBase> res = new List<MethodBase>();
  67. foreach (MethodBase mb in targets) {
  68. ParameterInfo[] pis = mb.GetParameters();
  69. if (pis.Length != args)
  70. continue;
  71. // Check each parameter type for an exact match.
  72. bool match = true;
  73. for (int i = 0; i < args; i++)
  74. if (pis[i].ParameterType != sig[i]) {
  75. match = false;
  76. break;
  77. }
  78. if (!match)
  79. continue;
  80. // Okay, we have a match, add it to the list.
  81. res.Add(mb);
  82. }
  83. return res.ToArray();
  84. }
  85. public BuiltinFunction Function {
  86. get {
  87. return _function;
  88. }
  89. }
  90. public virtual IList<MethodBase> Targets {
  91. get {
  92. return _function.Targets;
  93. }
  94. }
  95. public PythonTuple Functions {
  96. get {
  97. if (_allOverloads == null) {
  98. object[] res = new object[Targets.Count];
  99. int writeIndex = 0;
  100. foreach (MethodBase mb in Targets) {
  101. ParameterInfo[] pis = mb.GetParameters();
  102. Type[] types = new Type[pis.Length];
  103. for (int i = 0; i < pis.Length; i++) {
  104. types[i] = pis[i].ParameterType;
  105. }
  106. res[writeIndex++] = GetOverload(types, Targets, false);
  107. }
  108. Interlocked.CompareExchange(ref _allOverloads, PythonTuple.MakeTuple(res), null);
  109. }
  110. return _allOverloads;
  111. }
  112. }
  113. protected virtual object GetTargetFunction(BuiltinFunction bf) {
  114. return bf;
  115. }
  116. public virtual string/*!*/ __repr__(CodeContext/*!*/ context) {
  117. PythonDictionary overloadList = new PythonDictionary();
  118. foreach (MethodBase mb in Targets) {
  119. string key = DocBuilder.CreateAutoDoc(mb);
  120. overloadList[key] = Function;
  121. }
  122. return overloadList.__repr__(context);
  123. }
  124. }
  125. public class ConstructorOverloadMapper : BuiltinFunctionOverloadMapper {
  126. public ConstructorOverloadMapper(ConstructorFunction builtinFunction, object instance)
  127. : base(builtinFunction, instance) {
  128. }
  129. public override IList<MethodBase> Targets {
  130. get {
  131. return ((ConstructorFunction)Function).ConstructorTargets;
  132. }
  133. }
  134. protected override object GetTargetFunction(BuiltinFunction bf) {
  135. // return a function that's bound to the overloads, we'll
  136. // the user then calls this w/ the dynamic type, and the bound
  137. // function drops the class & calls the overload.
  138. if (bf.Targets[0].DeclaringType != typeof(InstanceOps)) {
  139. return new ConstructorFunction(InstanceOps.OverloadedNew, bf.Targets).BindToInstance(bf);
  140. }
  141. return base.GetTargetFunction(bf);
  142. }
  143. }
  144. }