PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/IronPython_2_0/Src/Microsoft.Scripting/Actions/BinderHelper.cs

#
C# | 224 lines | 164 code | 36 blank | 24 comment | 35 complexity | 054ff629f7b0b6cbbf03d5656c62152a MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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; using Microsoft;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Diagnostics;
  19. using Microsoft.Linq.Expressions;
  20. using System.Reflection;
  21. using Microsoft.Scripting.Utils;
  22. using Microsoft.Scripting.Generation;
  23. using Microsoft.Scripting.Runtime;
  24. namespace Microsoft.Scripting.Actions {
  25. using Ast = Microsoft.Linq.Expressions.Expression;
  26. public class BinderHelper {
  27. internal BinderHelper() { }
  28. // This can produce a IsCallable rule that returns the immutable constant isCallable.
  29. // Beware that objects can have a mutable callable property. Eg, in Python, assign or delete the __call__ attribute.
  30. public static RuleBuilder<T> MakeIsCallableRule<T>(CodeContext context, object self, bool isCallable) where T : class {
  31. RuleBuilder<T> rule = new RuleBuilder<T>();
  32. rule.MakeTest(CompilerHelpers.GetType(self));
  33. rule.Target =
  34. rule.MakeReturn(
  35. context.LanguageContext.Binder,
  36. Ast.Constant(isCallable)
  37. );
  38. return rule;
  39. }
  40. }
  41. public class BinderHelper<T, TAction> : BinderHelper
  42. where T : class
  43. where TAction : OldDynamicAction {
  44. private readonly CodeContext _context;
  45. private readonly TAction _action;
  46. public BinderHelper(CodeContext context, TAction action) {
  47. ContractUtils.RequiresNotNull(context, "context");
  48. ContractUtils.RequiresNotNull(action, "action");
  49. _context = context;
  50. _action = action;
  51. }
  52. protected CodeContext Context {
  53. get {
  54. return _context;
  55. }
  56. }
  57. protected TAction Action {
  58. get {
  59. return _action;
  60. }
  61. }
  62. protected DefaultBinder Binder {
  63. get {
  64. return (DefaultBinder)_context.LanguageContext.Binder;
  65. }
  66. }
  67. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] // TODO: fix
  68. public static UnaryExpression GetParamsList(RuleBuilder rule) {
  69. return Ast.Convert(
  70. rule.Parameters[rule.ParameterCount - 1],
  71. typeof(IList<object>)
  72. );
  73. }
  74. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] // TODO: fix
  75. public static Expression MakeParamsTest(object paramArg, Expression listArg) {
  76. return Ast.AndAlso(
  77. Ast.TypeIs(listArg, CompilerHelpers.GetType(paramArg)),
  78. Ast.Equal(
  79. Ast.Property(
  80. Ast.Convert(listArg, typeof(ICollection<object>)),
  81. typeof(ICollection<object>).GetProperty("Count")
  82. ),
  83. Ast.Constant(((IList<object>)paramArg).Count)
  84. )
  85. );
  86. }
  87. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] // TODO: fix
  88. public static Type[] GetArgumentTypes(OldCallAction action, object[] args) {
  89. List<Type> res = new List<Type>();
  90. for (int i = 1; i < args.Length; i++) {
  91. switch (action.Signature.GetArgumentKind(i - 1)) {
  92. case ArgumentKind.Simple:
  93. case ArgumentKind.Instance:
  94. case ArgumentKind.Named:
  95. res.Add(CompilerHelpers.GetType(args[i]));
  96. continue;
  97. case ArgumentKind.List:
  98. IList<object> list = args[i] as IList<object>;
  99. if (list == null) return null;
  100. for (int j = 0; j < list.Count; j++) {
  101. res.Add(CompilerHelpers.GetType(list[j]));
  102. }
  103. break;
  104. case ArgumentKind.Dictionary:
  105. // caller needs to process these...
  106. break;
  107. default:
  108. throw new NotImplementedException();
  109. }
  110. }
  111. return res.ToArray();
  112. }
  113. internal MethodInfo GetMethod(Type type, string name) {
  114. // declaring type takes precedence
  115. MethodInfo mi = type.GetMethod(name);
  116. if (mi != null) {
  117. return mi;
  118. }
  119. // then search extension types.
  120. Type curType = type;
  121. do {
  122. IList<Type> extTypes = Binder.GetExtensionTypes(curType);
  123. foreach (Type t in extTypes) {
  124. MethodInfo next = t.GetMethod(name);
  125. if (next != null) {
  126. if (mi != null) {
  127. throw new AmbiguousMatchException(String.Format("Found multiple members for {0} on type {1}", name, curType));
  128. }
  129. mi = next;
  130. }
  131. }
  132. if (mi != null) {
  133. return mi;
  134. }
  135. curType = curType.BaseType;
  136. } while (curType != null);
  137. return null;
  138. }
  139. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] // TODO: fix
  140. public static Expression MakeNecessaryTests(RuleBuilder rule, Type[] testTypes, IList<Expression> arguments) {
  141. Expression typeTest = Ast.Constant(true);
  142. if (testTypes != null) {
  143. for (int i = 0; i < testTypes.Length; i++) {
  144. if (testTypes[i] != null) {
  145. Debug.Assert(i < arguments.Count);
  146. typeTest = Ast.AndAlso(typeTest, rule.MakeTypeTest(testTypes[i], arguments[i]));
  147. }
  148. }
  149. }
  150. return typeTest;
  151. }
  152. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] // TODO: fix
  153. public static Expression MakeNecessaryTests(RuleBuilder rule, IList<Type[]> necessaryTests, Expression[] arguments) {
  154. if (necessaryTests.Count == 0) {
  155. return Ast.Constant(true);
  156. }
  157. Type[] mostSpecificTypes = null; // This is the final types that will be checked after inspecting all the sets
  158. for (int i = 0; i < necessaryTests.Count; i++) {
  159. Type[] currentSet = necessaryTests[i];
  160. if (currentSet == null) {
  161. // The current set is missing. Ignore it
  162. continue;
  163. }
  164. // All the sets should be of the same size
  165. Debug.Assert(currentSet.Length == arguments.Length);
  166. if (mostSpecificTypes == null) {
  167. mostSpecificTypes = new Type[currentSet.Length];
  168. }
  169. // For each type in the current set, check the type with the corresponding type in the previous sets
  170. for (int j = 0; j < currentSet.Length; j++) {
  171. if (mostSpecificTypes[j] == null || mostSpecificTypes[j].IsAssignableFrom(currentSet[j])) {
  172. // no test yet or more specific test
  173. mostSpecificTypes[j] = currentSet[j];
  174. } else {
  175. // All sets should have compatible types in each slot
  176. Debug.Assert(currentSet[j] == null || currentSet[j].IsAssignableFrom(mostSpecificTypes[j]));
  177. }
  178. }
  179. }
  180. return MakeNecessaryTests(rule, mostSpecificTypes, arguments);
  181. }
  182. protected bool PrivateBinding {
  183. get {
  184. return Context.LanguageContext.DomainManager.Configuration.PrivateBinding;
  185. }
  186. }
  187. }
  188. }