PageRenderTime 36ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/IronPython_Main/Runtime/Microsoft.Dynamic/Runtime/BinderOps.cs

#
C# | 258 lines | 186 code | 40 blank | 32 comment | 41 complexity | 333b513c8c4f12f82d3513e12ff8eeb0 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 Apache License, Version 2.0. 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 Apache License, Version 2.0, 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 Apache License, Version 2.0.
  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;
  22. using System.Collections.Generic;
  23. using System.Reflection;
  24. using System.Diagnostics;
  25. using System.Dynamic;
  26. using System.Text;
  27. using Microsoft.Scripting.Actions;
  28. using Microsoft.Scripting.Generation;
  29. using Microsoft.Scripting.Utils;
  30. namespace Microsoft.Scripting.Runtime {
  31. /// <summary>
  32. /// Helper methods that calls are generated to from the default DLR binders.
  33. /// </summary>
  34. public static class BinderOps {
  35. /// <summary>
  36. /// Helper function to combine an object array with a sequence of additional parameters that has been splatted for a function call.
  37. /// </summary>
  38. public static object[] GetCombinedParameters(object[] initialArgs, object additionalArgs) {
  39. IList listArgs = additionalArgs as IList;
  40. if (listArgs == null) {
  41. IEnumerable ie = additionalArgs as IEnumerable;
  42. if (ie == null) {
  43. throw new InvalidOperationException("args must be iterable");
  44. }
  45. listArgs = new List<object>();
  46. foreach (object o in ie) {
  47. listArgs.Add(o);
  48. }
  49. }
  50. object[] res = new object[initialArgs.Length + listArgs.Count];
  51. Array.Copy(initialArgs, res, initialArgs.Length);
  52. listArgs.CopyTo(res, initialArgs.Length);
  53. return res;
  54. }
  55. public static Dictionary<TKey, TValue> MakeDictionary<TKey, TValue>(string[] names, object[] values) {
  56. Debug.Assert(typeof(TKey) == typeof(string) || typeof(TKey) == typeof(object));
  57. Dictionary<TKey, TValue> res = new Dictionary<TKey, TValue>();
  58. IDictionary id = (IDictionary)res;
  59. for (int i = 0; i < names.Length; i++) {
  60. id[names[i]] = values[i];
  61. }
  62. return res;
  63. }
  64. public static ArgumentTypeException BadArgumentsForOperation(ExpressionType op, params object[] args) {
  65. StringBuilder message = new StringBuilder("unsupported operand type(s) for operation ");
  66. message.Append(op.ToString());
  67. message.Append(": ");
  68. string comma = "";
  69. foreach (object o in args) {
  70. message.Append(comma);
  71. message.Append(CompilerHelpers.GetType(o));
  72. comma = ", ";
  73. }
  74. throw new ArgumentTypeException(message.ToString());
  75. }
  76. // formalNormalArgumentCount - does not include FuncDefFlags.ArgList and FuncDefFlags.KwDict
  77. // defaultArgumentCount - How many arguments in the method declaration have a default value?
  78. // providedArgumentCount - How many arguments are passed in at the call site?
  79. // hasArgList - Is the method declaration of the form "foo(*argList)"?
  80. // keywordArgumentsProvided - Does the call site specify keyword arguments?
  81. public static ArgumentTypeException TypeErrorForIncorrectArgumentCount(
  82. string methodName,
  83. int formalNormalArgumentCount,
  84. int defaultArgumentCount,
  85. int providedArgumentCount,
  86. bool hasArgList,
  87. bool keywordArgumentsProvided) {
  88. return TypeErrorForIncorrectArgumentCount(methodName, formalNormalArgumentCount, formalNormalArgumentCount, defaultArgumentCount, providedArgumentCount, hasArgList, keywordArgumentsProvided);
  89. }
  90. public static ArgumentTypeException TypeErrorForIncorrectArgumentCount(
  91. string methodName,
  92. int minFormalNormalArgumentCount,
  93. int maxFormalNormalArgumentCount,
  94. int defaultArgumentCount,
  95. int providedArgumentCount,
  96. bool hasArgList,
  97. bool keywordArgumentsProvided) {
  98. int formalCount;
  99. string formalCountQualifier;
  100. string nonKeyword = keywordArgumentsProvided ? "non-keyword " : "";
  101. if (defaultArgumentCount > 0 || hasArgList || minFormalNormalArgumentCount != maxFormalNormalArgumentCount) {
  102. if (providedArgumentCount < minFormalNormalArgumentCount || maxFormalNormalArgumentCount == Int32.MaxValue) {
  103. formalCountQualifier = "at least";
  104. formalCount = minFormalNormalArgumentCount - defaultArgumentCount;
  105. } else {
  106. formalCountQualifier = "at most";
  107. formalCount = maxFormalNormalArgumentCount;
  108. }
  109. } else if (minFormalNormalArgumentCount == 0) {
  110. return ScriptingRuntimeHelpers.SimpleTypeError(string.Format("{0}() takes no arguments ({1} given)", methodName, providedArgumentCount));
  111. } else {
  112. formalCountQualifier = "exactly";
  113. formalCount = minFormalNormalArgumentCount;
  114. }
  115. return new ArgumentTypeException(string.Format(
  116. "{0}() takes {1} {2} {3}argument{4} ({5} given)",
  117. methodName, // 0
  118. formalCountQualifier, // 1
  119. formalCount, // 2
  120. nonKeyword, // 3
  121. formalCount == 1 ? "" : "s", // 4
  122. providedArgumentCount)); // 5
  123. }
  124. public static ArgumentTypeException TypeErrorForIncorrectArgumentCount(string name, int formalNormalArgumentCount, int defaultArgumentCount, int providedArgumentCount) {
  125. return TypeErrorForIncorrectArgumentCount(name, formalNormalArgumentCount, defaultArgumentCount, providedArgumentCount, false, false);
  126. }
  127. public static ArgumentTypeException TypeErrorForIncorrectArgumentCount(string name, int expected, int received) {
  128. return TypeErrorForIncorrectArgumentCount(name, expected, 0, received);
  129. }
  130. public static ArgumentTypeException TypeErrorForExtraKeywordArgument(string name, string argumentName) {
  131. return new ArgumentTypeException(String.Format("{0}() got an unexpected keyword argument '{1}'", name, argumentName));
  132. }
  133. public static ArgumentTypeException TypeErrorForDuplicateKeywordArgument(string name, string argumentName) {
  134. return new ArgumentTypeException(String.Format("{0}() got multiple values for keyword argument '{1}'", name, argumentName));
  135. }
  136. public static ArgumentTypeException TypeErrorForNonInferrableMethod(string name) {
  137. return new ArgumentTypeException(String.Format("The type arguments for method '{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly.", name));
  138. }
  139. public static ArgumentTypeException SimpleTypeError(string message) {
  140. return new ArgumentTypeException(message);
  141. }
  142. public static ArgumentTypeException InvalidSplatteeError(string name, string typeName) {
  143. return new ArgumentTypeException(String.Format("{0}() argument after * must be a sequence, not {1}", name, typeName));
  144. }
  145. public static object InvokeMethod(MethodBase mb, object obj, object[] args) {
  146. try {
  147. return mb.Invoke(obj, args);
  148. } catch (TargetInvocationException tie) {
  149. throw tie.InnerException;
  150. }
  151. }
  152. public static object InvokeConstructor(ConstructorInfo ci, object[] args) {
  153. try {
  154. return ci.Invoke(args);
  155. } catch (TargetInvocationException tie) {
  156. throw tie.InnerException;
  157. }
  158. }
  159. // TODO: just emit this in the generated code
  160. public static bool CheckDictionaryMembers(IDictionary dict, string[] names, Type[] types) {
  161. if (dict.Count != names.Length) return false;
  162. for (int i = 0; i < names.Length; i++) {
  163. string name = names[i];
  164. if (!dict.Contains(name)) {
  165. return false;
  166. }
  167. if (types != null) {
  168. if (CompilerHelpers.GetType(dict[name]) != types[i]) {
  169. return false;
  170. }
  171. }
  172. }
  173. return true;
  174. }
  175. public static IList<string> GetStringMembers(IList<object> members) {
  176. List<string> res = new List<string>();
  177. foreach (object o in members) {
  178. string str = o as string;
  179. if (str != null) {
  180. res.Add(str);
  181. }
  182. }
  183. return res;
  184. }
  185. /// <summary>
  186. /// EventInfo.EventHandlerType getter is marked SecuritySafeCritical in CoreCLR
  187. /// This method is to get to the property without using Reflection
  188. /// </summary>
  189. /// <param name="eventInfo"></param>
  190. /// <returns></returns>
  191. public static Type GetEventHandlerType(EventInfo eventInfo) {
  192. ContractUtils.RequiresNotNull(eventInfo, "eventInfo");
  193. return eventInfo.EventHandlerType;
  194. }
  195. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] // TODO: fix
  196. public static void SetEvent(EventTracker eventTracker, object value) {
  197. EventTracker et = value as EventTracker;
  198. if (et != null) {
  199. if (et != eventTracker) {
  200. throw new ArgumentException(String.Format("expected event from {0}.{1}, got event from {2}.{3}",
  201. eventTracker.DeclaringType.Name,
  202. eventTracker.Name,
  203. et.DeclaringType.Name,
  204. et.Name));
  205. }
  206. return;
  207. }
  208. BoundMemberTracker bmt = value as BoundMemberTracker;
  209. if (bmt == null) throw new ArgumentTypeException("expected bound event, got " + CompilerHelpers.GetType(value).Name);
  210. if (bmt.BoundTo.MemberType != TrackerTypes.Event) throw new ArgumentTypeException("expected bound event, got " + bmt.BoundTo.MemberType.ToString());
  211. if (bmt.BoundTo != eventTracker) throw new ArgumentException(String.Format("expected event from {0}.{1}, got event from {2}.{3}",
  212. eventTracker.DeclaringType.Name,
  213. eventTracker.Name,
  214. bmt.BoundTo.DeclaringType.Name,
  215. bmt.BoundTo.Name));
  216. }
  217. }
  218. }