PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/DICK.B1/IronPython/Runtime/Binding/PythonGetIndexBinder.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 202 lines | 148 code | 38 blank | 16 comment | 81 complexity | 95d813a6338ef72d36f48b8f901b4d4f 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 !CLR2
  16. using System.Linq.Expressions;
  17. #else
  18. using Microsoft.Scripting.Ast;
  19. #endif
  20. using System;
  21. using System.Dynamic;
  22. using System.Reflection;
  23. using System.Runtime.CompilerServices;
  24. using Microsoft.Scripting.Runtime;
  25. using Microsoft.Scripting.Utils;
  26. using Microsoft.Scripting.Generation;
  27. using IronPython.Runtime.Operations;
  28. namespace IronPython.Runtime.Binding {
  29. using Ast = Expression;
  30. using AstUtils = Microsoft.Scripting.Ast.Utils;
  31. class PythonGetIndexBinder : GetIndexBinder, IPythonSite, IExpressionSerializable {
  32. private readonly PythonContext/*!*/ _context;
  33. public PythonGetIndexBinder(PythonContext/*!*/ context, int argCount)
  34. : base(new CallInfo(argCount)) {
  35. _context = context;
  36. }
  37. public override DynamicMetaObject FallbackGetIndex(DynamicMetaObject target, DynamicMetaObject[] indexes, DynamicMetaObject errorSuggestion) {
  38. #if !SILVERLIGHT
  39. DynamicMetaObject com;
  40. if (Microsoft.Scripting.ComInterop.ComBinder.TryBindGetIndex(this, target, BindingHelpers.GetComArguments(indexes), out com)) {
  41. return com;
  42. }
  43. #endif
  44. return PythonProtocol.Index(this, PythonIndexType.GetItem, ArrayUtils.Insert(target, indexes), errorSuggestion);
  45. }
  46. public override T BindDelegate<T>(CallSite<T> site, object[] args) {
  47. ParameterInfo[] prms = typeof(T).GetMethod("Invoke").GetParameters();
  48. if (CompilerHelpers.GetType(args[1]) == typeof(int)) {
  49. if (CompilerHelpers.GetType(args[0]) == typeof(List)) {
  50. if (typeof(T) == typeof(Func<CallSite, object, object, object>)) {
  51. return (T)(object)new Func<CallSite, object, object, object>(ListIndex);
  52. } else if (typeof(T) == typeof(Func<CallSite, object, int, object>)) {
  53. return (T)(object)new Func<CallSite, object, int, object>(ListIndex);
  54. } else if (typeof(T) == typeof(Func<CallSite, List, object, object>)) {
  55. return (T)(object)new Func<CallSite, List, object, object>(ListIndex);
  56. }
  57. } else if (CompilerHelpers.GetType(args[0]) == typeof(PythonTuple)) {
  58. if (typeof(T) == typeof(Func<CallSite, object, object, object>)) {
  59. return (T)(object)new Func<CallSite, object, object, object>(TupleIndex);
  60. } else if (typeof(T) == typeof(Func<CallSite, object, int, object>)) {
  61. return (T)(object)new Func<CallSite, object, int, object>(TupleIndex);
  62. } else if (typeof(T) == typeof(Func<CallSite, PythonTuple, object, object>)) {
  63. return (T)(object)new Func<CallSite, PythonTuple, object, object>(TupleIndex);
  64. }
  65. } else if (CompilerHelpers.GetType(args[0]) == typeof(string)) {
  66. if (typeof(T) == typeof(Func<CallSite, object, object, object>)) {
  67. return (T)(object)new Func<CallSite, object, object, object>(StringIndex);
  68. } else if (typeof(T) == typeof(Func<CallSite, object, int, object>)) {
  69. return (T)(object)new Func<CallSite, object, int, object>(StringIndex);
  70. } else if (typeof(T) == typeof(Func<CallSite, string, object, object>)) {
  71. return (T)(object)new Func<CallSite, string, object, object>(StringIndex);
  72. }
  73. }
  74. }
  75. return base.BindDelegate<T>(site, args);
  76. }
  77. private object ListIndex(CallSite site, List target, object index) {
  78. if (target != null && index != null && index.GetType() == typeof(int)) {
  79. return target[(int)index];
  80. }
  81. return ((CallSite<Func<CallSite, List, object, object>>)site).Update(site, target, index);
  82. }
  83. private object ListIndex(CallSite site, object target, object index) {
  84. // using as is ok here because [] is virtual and will call the user method if
  85. // we have a user defined subclass of list.
  86. List lst = target as List;
  87. if (lst != null && index != null && index.GetType() == typeof(int)) {
  88. return lst[(int)index];
  89. }
  90. return ((CallSite<Func<CallSite, object, object, object>>)site).Update(site, target, index);
  91. }
  92. private object ListIndex(CallSite site, object target, int index) {
  93. List lst = target as List;
  94. if (lst != null) {
  95. return lst[index];
  96. }
  97. return ((CallSite<Func<CallSite, object, int, object>>)site).Update(site, target, index);
  98. }
  99. private object TupleIndex(CallSite site, PythonTuple target, object index) {
  100. if (target != null && index != null && index.GetType() == typeof(int)) {
  101. return target[(int)index];
  102. }
  103. return ((CallSite<Func<CallSite, PythonTuple, object, object>>)site).Update(site, target, index);
  104. }
  105. private object TupleIndex(CallSite site, object target, object index) {
  106. PythonTuple lst = target as PythonTuple;
  107. if (lst != null && index != null && index.GetType() == typeof(int)) {
  108. return lst[(int)index];
  109. }
  110. return ((CallSite<Func<CallSite, object, object, object>>)site).Update(site, target, index);
  111. }
  112. private object TupleIndex(CallSite site, object target, int index) {
  113. PythonTuple lst = target as PythonTuple;
  114. if (lst != null) {
  115. return lst[index];
  116. }
  117. return ((CallSite<Func<CallSite, object, int, object>>)site).Update(site, target, index);
  118. }
  119. private object StringIndex(CallSite site, string target, object index) {
  120. if (target != null && index != null && index.GetType() == typeof(int)) {
  121. return StringOps.GetItem(target, (int)index);
  122. }
  123. return ((CallSite<Func<CallSite, string, object, object>>)site).Update(site, target, index);
  124. }
  125. private object StringIndex(CallSite site, object target, object index) {
  126. string str = target as string;
  127. if (str != null && index != null && index.GetType() == typeof(int)) {
  128. return StringOps.GetItem(str, (int)index);
  129. }
  130. return ((CallSite<Func<CallSite, object, object, object>>)site).Update(site, target, index);
  131. }
  132. private object StringIndex(CallSite site, object target, int index) {
  133. string str = target as string;
  134. if (str != null) {
  135. return StringOps.GetItem(str, index);
  136. }
  137. return ((CallSite<Func<CallSite, object, int, object>>)site).Update(site, target, index);
  138. }
  139. public override int GetHashCode() {
  140. return base.GetHashCode() ^ _context.Binder.GetHashCode();
  141. }
  142. public override bool Equals(object obj) {
  143. PythonGetIndexBinder ob = obj as PythonGetIndexBinder;
  144. if (ob == null) {
  145. return false;
  146. }
  147. return ob._context.Binder == _context.Binder && base.Equals(obj);
  148. }
  149. #region IPythonSite Members
  150. public PythonContext/*!*/ Context {
  151. get { return _context; }
  152. }
  153. #endregion
  154. #region IExpressionSerializable Members
  155. public Expression/*!*/ CreateExpression() {
  156. return Ast.Call(
  157. typeof(PythonOps).GetMethod("MakeGetIndexAction"),
  158. BindingHelpers.CreateBinderStateExpression(),
  159. AstUtils.Constant(CallInfo.ArgumentCount)
  160. );
  161. }
  162. #endregion
  163. }
  164. }