PageRenderTime 48ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/IronPython/Runtime/Binding/PythonGetIndexBinder.cs

http://github.com/IronLanguages/main
C# | 200 lines | 147 code | 37 blank | 16 comment | 81 complexity | c924995b08d032fd58ab776aeaf5cbac MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  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 FEATURE_CORE_DLR
  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 FEATURE_COM
  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. if (CompilerHelpers.GetType(args[1]) == typeof(int)) {
  48. if (CompilerHelpers.GetType(args[0]) == typeof(List)) {
  49. if (typeof(T) == typeof(Func<CallSite, object, object, object>)) {
  50. return (T)(object)new Func<CallSite, object, object, object>(ListIndex);
  51. } else if (typeof(T) == typeof(Func<CallSite, object, int, object>)) {
  52. return (T)(object)new Func<CallSite, object, int, object>(ListIndex);
  53. } else if (typeof(T) == typeof(Func<CallSite, List, object, object>)) {
  54. return (T)(object)new Func<CallSite, List, object, object>(ListIndex);
  55. }
  56. } else if (CompilerHelpers.GetType(args[0]) == typeof(PythonTuple)) {
  57. if (typeof(T) == typeof(Func<CallSite, object, object, object>)) {
  58. return (T)(object)new Func<CallSite, object, object, object>(TupleIndex);
  59. } else if (typeof(T) == typeof(Func<CallSite, object, int, object>)) {
  60. return (T)(object)new Func<CallSite, object, int, object>(TupleIndex);
  61. } else if (typeof(T) == typeof(Func<CallSite, PythonTuple, object, object>)) {
  62. return (T)(object)new Func<CallSite, PythonTuple, object, object>(TupleIndex);
  63. }
  64. } else if (CompilerHelpers.GetType(args[0]) == typeof(string)) {
  65. if (typeof(T) == typeof(Func<CallSite, object, object, object>)) {
  66. return (T)(object)new Func<CallSite, object, object, object>(StringIndex);
  67. } else if (typeof(T) == typeof(Func<CallSite, object, int, object>)) {
  68. return (T)(object)new Func<CallSite, object, int, object>(StringIndex);
  69. } else if (typeof(T) == typeof(Func<CallSite, string, object, object>)) {
  70. return (T)(object)new Func<CallSite, string, object, object>(StringIndex);
  71. }
  72. }
  73. }
  74. return base.BindDelegate<T>(site, args);
  75. }
  76. private object ListIndex(CallSite site, List target, object index) {
  77. if (target != null && index != null && index.GetType() == typeof(int)) {
  78. return target[(int)index];
  79. }
  80. return ((CallSite<Func<CallSite, List, object, object>>)site).Update(site, target, index);
  81. }
  82. private object ListIndex(CallSite site, object target, object index) {
  83. // using as is ok here because [] is virtual and will call the user method if
  84. // we have a user defined subclass of list.
  85. List lst = target as List;
  86. if (lst != null && index != null && index.GetType() == typeof(int)) {
  87. return lst[(int)index];
  88. }
  89. return ((CallSite<Func<CallSite, object, object, object>>)site).Update(site, target, index);
  90. }
  91. private object ListIndex(CallSite site, object target, int index) {
  92. List lst = target as List;
  93. if (lst != null) {
  94. return lst[index];
  95. }
  96. return ((CallSite<Func<CallSite, object, int, object>>)site).Update(site, target, index);
  97. }
  98. private object TupleIndex(CallSite site, PythonTuple target, object index) {
  99. if (target != null && index != null && index.GetType() == typeof(int)) {
  100. return target[(int)index];
  101. }
  102. return ((CallSite<Func<CallSite, PythonTuple, object, object>>)site).Update(site, target, index);
  103. }
  104. private object TupleIndex(CallSite site, object target, object index) {
  105. PythonTuple lst = target as PythonTuple;
  106. if (lst != null && index != null && index.GetType() == typeof(int)) {
  107. return lst[(int)index];
  108. }
  109. return ((CallSite<Func<CallSite, object, object, object>>)site).Update(site, target, index);
  110. }
  111. private object TupleIndex(CallSite site, object target, int index) {
  112. PythonTuple lst = target as PythonTuple;
  113. if (lst != null) {
  114. return lst[index];
  115. }
  116. return ((CallSite<Func<CallSite, object, int, object>>)site).Update(site, target, index);
  117. }
  118. private object StringIndex(CallSite site, string target, object index) {
  119. if (target != null && index != null && index.GetType() == typeof(int)) {
  120. return StringOps.GetItem(target, (int)index);
  121. }
  122. return ((CallSite<Func<CallSite, string, object, object>>)site).Update(site, target, index);
  123. }
  124. private object StringIndex(CallSite site, object target, object index) {
  125. string str = target as string;
  126. if (str != null && index != null && index.GetType() == typeof(int)) {
  127. return StringOps.GetItem(str, (int)index);
  128. }
  129. return ((CallSite<Func<CallSite, object, object, object>>)site).Update(site, target, index);
  130. }
  131. private object StringIndex(CallSite site, object target, int index) {
  132. string str = target as string;
  133. if (str != null) {
  134. return StringOps.GetItem(str, index);
  135. }
  136. return ((CallSite<Func<CallSite, object, int, object>>)site).Update(site, target, index);
  137. }
  138. public override int GetHashCode() {
  139. return base.GetHashCode() ^ _context.Binder.GetHashCode();
  140. }
  141. public override bool Equals(object obj) {
  142. PythonGetIndexBinder ob = obj as PythonGetIndexBinder;
  143. if (ob == null) {
  144. return false;
  145. }
  146. return ob._context.Binder == _context.Binder && base.Equals(obj);
  147. }
  148. #region IPythonSite Members
  149. public PythonContext/*!*/ Context {
  150. get { return _context; }
  151. }
  152. #endregion
  153. #region IExpressionSerializable Members
  154. public Expression/*!*/ CreateExpression() {
  155. return Ast.Call(
  156. typeof(PythonOps).GetMethod("MakeGetIndexAction"),
  157. BindingHelpers.CreateBinderStateExpression(),
  158. AstUtils.Constant(CallInfo.ArgumentCount)
  159. );
  160. }
  161. #endregion
  162. }
  163. }