PageRenderTime 43ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Microsoft.Scripting/Actions/BinderHelper.cs

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