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

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

https://bitbucket.org/williamybs/uidipythontool
C# | 323 lines | 253 code | 52 blank | 18 comment | 135 complexity | cff6b47d2cecfaf222496fa2ceb0d79b 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.Collections;
  22. using System.Collections.Generic;
  23. using System.Dynamic;
  24. using System.Runtime.CompilerServices;
  25. using Microsoft.Scripting.Generation;
  26. using Microsoft.Scripting.Runtime;
  27. using Microsoft.Scripting.Utils;
  28. using IronPython.Runtime.Operations;
  29. using IronPython.Runtime.Types;
  30. using AstUtils = Microsoft.Scripting.Ast.Utils;
  31. namespace IronPython.Runtime.Binding {
  32. using Ast = Expression;
  33. class PythonOperationBinder : DynamicMetaObjectBinder, IPythonSite, IExpressionSerializable {
  34. private readonly PythonContext/*!*/ _context;
  35. private readonly PythonOperationKind _operation;
  36. public PythonOperationBinder(PythonContext/*!*/ context, PythonOperationKind/*!*/ operation) {
  37. _context = context;
  38. _operation = operation;
  39. }
  40. public override DynamicMetaObject Bind(DynamicMetaObject target, DynamicMetaObject[] args) {
  41. IPythonOperable op = target as IPythonOperable;
  42. if (op != null) {
  43. DynamicMetaObject res = op.BindOperation(this, ArrayUtils.Insert(target, args));
  44. if (res != null) {
  45. return res;
  46. }
  47. }
  48. return PythonProtocol.Operation(this, ArrayUtils.Insert(target, args));
  49. }
  50. public override T BindDelegate<T>(CallSite<T> site, object[] args) {
  51. switch(_operation) {
  52. case PythonOperationKind.Hash:
  53. if (CompilerHelpers.GetType(args[0]) == typeof(PythonType)) {
  54. if (typeof(T) == typeof(Func<CallSite, object, int>)) {
  55. return (T)(object)new Func<CallSite, object, int>(HashPythonType);
  56. }
  57. } else if (args[0] is OldClass) {
  58. if (typeof(T) == typeof(Func<CallSite, object, int>)) {
  59. return (T)(object)new Func<CallSite, object, int>(HashOldClass);
  60. }
  61. }
  62. break;
  63. case PythonOperationKind.Compare:
  64. if (CompilerHelpers.GetType(args[0]) == typeof(string) &&
  65. CompilerHelpers.GetType(args[1]) == typeof(string)) {
  66. if (typeof(T) == typeof(Func<CallSite, object, object, int>)) {
  67. return (T)(object)new Func<CallSite, object, object, int>(CompareStrings);
  68. }
  69. }
  70. break;
  71. case PythonOperationKind.GetEnumeratorForIteration:
  72. if (CompilerHelpers.GetType(args[0]) == typeof(List)) {
  73. if (typeof(T) == typeof(Func<CallSite, List, KeyValuePair<IEnumerator, IDisposable>>)) {
  74. return (T)(object)new Func<CallSite, List, KeyValuePair<IEnumerator, IDisposable>>(GetListEnumerator);
  75. }
  76. return (T)(object)new Func<CallSite, object, KeyValuePair<IEnumerator, IDisposable>>(GetListEnumerator);
  77. } else if (CompilerHelpers.GetType(args[0]) == typeof(PythonTuple)) {
  78. if (typeof(T) == typeof(Func<CallSite, PythonTuple, KeyValuePair<IEnumerator, IDisposable>>)) {
  79. return (T)(object)new Func<CallSite, PythonTuple, KeyValuePair<IEnumerator, IDisposable>>(GetTupleEnumerator);
  80. }
  81. return (T)(object)new Func<CallSite, object, KeyValuePair<IEnumerator, IDisposable>>(GetTupleEnumerator);
  82. }
  83. break;
  84. case PythonOperationKind.Contains:
  85. if (CompilerHelpers.GetType(args[1]) == typeof(List)) {
  86. Type tType = typeof(T);
  87. if (tType == typeof(Func<CallSite, object, object, bool>)) {
  88. return (T)(object)new Func<CallSite, object, object, bool>(ListContains<object>);
  89. } else if (tType == typeof(Func<CallSite, object, List, bool>)) {
  90. return (T)(object)new Func<CallSite, object, List, bool>(ListContains);
  91. } else if (tType == typeof(Func<CallSite, int, object, bool>)) {
  92. return (T)(object)new Func<CallSite, int, object, bool>(ListContains<int>);
  93. } else if (tType == typeof(Func<CallSite, string, object, bool>)) {
  94. return (T)(object)new Func<CallSite, string, object, bool>(ListContains<string>);
  95. } else if (tType == typeof(Func<CallSite, double, object, bool>)) {
  96. return (T)(object)new Func<CallSite, double, object, bool>(ListContains<double>);
  97. } else if (tType == typeof(Func<CallSite, PythonTuple, object, bool>)) {
  98. return (T)(object)new Func<CallSite, PythonTuple, object, bool>(ListContains<PythonTuple>);
  99. }
  100. } else if (CompilerHelpers.GetType(args[1]) == typeof(PythonTuple)) {
  101. Type tType = typeof(T);
  102. if (tType == typeof(Func<CallSite, object, object, bool>)) {
  103. return (T)(object)new Func<CallSite, object, object, bool>(TupleContains<object>);
  104. } else if (tType == typeof(Func<CallSite, object, PythonTuple, bool>)) {
  105. return (T)(object)new Func<CallSite, object, PythonTuple, bool>(TupleContains);
  106. } else if (tType == typeof(Func<CallSite, int, object, bool>)) {
  107. return (T)(object)new Func<CallSite, int, object, bool>(TupleContains<int>);
  108. } else if (tType == typeof(Func<CallSite, string, object, bool>)) {
  109. return (T)(object)new Func<CallSite, string, object, bool>(TupleContains<string>);
  110. } else if (tType == typeof(Func<CallSite, double, object, bool>)) {
  111. return (T)(object)new Func<CallSite, double, object, bool>(TupleContains<double>);
  112. } else if (tType == typeof(Func<CallSite, PythonTuple, object, bool>)) {
  113. return (T)(object)new Func<CallSite, PythonTuple, object, bool>(TupleContains<PythonTuple>);
  114. }
  115. } else if (CompilerHelpers.GetType(args[0]) == typeof(string) && CompilerHelpers.GetType(args[1]) == typeof(string)) {
  116. Type tType = typeof(T);
  117. if (tType == typeof(Func<CallSite, object, object, bool>)) {
  118. return (T)(object)new Func<CallSite, object, object, bool>(StringContains);
  119. } else if(tType == typeof(Func<CallSite, string, object, bool>)) {
  120. return (T)(object)new Func<CallSite, string, object, bool>(StringContains);
  121. } else if (tType == typeof(Func<CallSite, object, string, bool>)) {
  122. return (T)(object)new Func<CallSite, object, string, bool>(StringContains);
  123. } else if (tType == typeof(Func<CallSite, string, string, bool>)) {
  124. return (T)(object)new Func<CallSite, string, string, bool>(StringContains);
  125. }
  126. } else if (CompilerHelpers.GetType(args[1]) == typeof(SetCollection)) {
  127. if (typeof(T) == typeof(Func<CallSite, object, object, bool>)) {
  128. return (T)(object)new Func<CallSite, object, object, bool>(SetContains);
  129. }
  130. }
  131. break;
  132. }
  133. return base.BindDelegate<T>(site, args);
  134. }
  135. private KeyValuePair<IEnumerator, IDisposable> GetListEnumerator(CallSite site, List value) {
  136. return new KeyValuePair<IEnumerator,IDisposable>(new ListIterator(value), null);
  137. }
  138. private KeyValuePair<IEnumerator, IDisposable> GetListEnumerator(CallSite site, object value) {
  139. if (value != null && value.GetType() == typeof(List)) {
  140. return new KeyValuePair<IEnumerator,IDisposable>(new ListIterator((List)value), null);
  141. }
  142. return ((CallSite<Func<CallSite, object, KeyValuePair<IEnumerator, IDisposable>>>)site).Update(site, value);
  143. }
  144. private KeyValuePair<IEnumerator, IDisposable> GetTupleEnumerator(CallSite site, PythonTuple value) {
  145. return new KeyValuePair<IEnumerator,IDisposable>(new TupleEnumerator(value), null);
  146. }
  147. private KeyValuePair<IEnumerator, IDisposable> GetTupleEnumerator(CallSite site, object value) {
  148. if (value != null && value.GetType() == typeof(PythonTuple)) {
  149. return new KeyValuePair<IEnumerator, IDisposable>(new TupleEnumerator((PythonTuple)value), null);
  150. }
  151. return ((CallSite<Func<CallSite, object, KeyValuePair<IEnumerator, IDisposable>>>)site).Update(site, value);
  152. }
  153. private bool ListContains(CallSite site, object other, List value) {
  154. return value.ContainsWorker(other);
  155. }
  156. private bool ListContains<TOther>(CallSite site, TOther other, object value) {
  157. if (value != null && value.GetType() == typeof(List)) {
  158. return ((List)value).ContainsWorker(other);
  159. }
  160. return ((CallSite<Func<CallSite, TOther, object, bool>>)site).Update(site, other, value);
  161. }
  162. private bool TupleContains(CallSite site, object other, PythonTuple value) {
  163. return value.Contains(other);
  164. }
  165. private bool TupleContains<TOther>(CallSite site, TOther other, object value) {
  166. if (value != null && value.GetType() == typeof(PythonTuple)) {
  167. return ((PythonTuple)value).Contains(other);
  168. }
  169. return ((CallSite<Func<CallSite, TOther, object, bool>>)site).Update(site, other, value);
  170. }
  171. private bool StringContains(CallSite site, string other, string value) {
  172. if (other != null && value != null) {
  173. return StringOps.__contains__(value, other);
  174. }
  175. return ((CallSite<Func<CallSite, string, string, bool>>)site).Update(site, other, value);
  176. }
  177. private bool StringContains(CallSite site, object other, string value) {
  178. if (other is string && value != null) {
  179. return StringOps.__contains__(value, (string)other);
  180. }
  181. return ((CallSite<Func<CallSite, object, string, bool>>)site).Update(site, other, value);
  182. }
  183. private bool StringContains(CallSite site, string other, object value) {
  184. if (value is string && other != null) {
  185. return StringOps.__contains__((string)value, other);
  186. }
  187. return ((CallSite<Func<CallSite, string, object, bool>>)site).Update(site, other, value);
  188. }
  189. private bool StringContains(CallSite site, object other, object value) {
  190. if (value is string && other is string) {
  191. return StringOps.__contains__((string)value, (string)other);
  192. }
  193. return ((CallSite<Func<CallSite, object, object, bool>>)site).Update(site, other, value);
  194. }
  195. private bool SetContains(CallSite site, object other, object value) {
  196. if (value != null && value.GetType() == typeof(SetCollection)) {
  197. return ((SetCollection)value).__contains__(other);
  198. }
  199. return ((CallSite<Func<CallSite, object, object, bool>>)site).Update(site, other, value);
  200. }
  201. private int HashPythonType(CallSite site, object value) {
  202. if (value != null && value.GetType() == typeof(PythonType)) {
  203. return value.GetHashCode();
  204. }
  205. return ((CallSite<Func<CallSite, object, int>>)site).Update(site, value);
  206. }
  207. private int HashOldClass(CallSite site, object value) {
  208. // OldClass is sealed, an is check is good enough.
  209. if (value is OldClass) {
  210. return value.GetHashCode();
  211. }
  212. return ((CallSite<Func<CallSite, object, int>>)site).Update(site, value);
  213. }
  214. private int CompareStrings(CallSite site, object arg0, object arg1) {
  215. if (arg0 != null && arg0.GetType() == typeof(string) &&
  216. arg1 != null && arg1.GetType() == typeof(string)) {
  217. return StringOps.Compare((string)arg0, (string)arg1);
  218. }
  219. return ((CallSite<Func<CallSite, object, object, int>>)site).Update(site, arg0, arg1);
  220. }
  221. public PythonOperationKind Operation {
  222. get {
  223. return _operation;
  224. }
  225. }
  226. /// <summary>
  227. /// The result type of the operation.
  228. /// </summary>
  229. public override Type ReturnType {
  230. get {
  231. switch (Operation & (~PythonOperationKind.DisableCoerce)) {
  232. case PythonOperationKind.Compare: return typeof(int);
  233. case PythonOperationKind.IsCallable: return typeof(bool);
  234. case PythonOperationKind.Hash: return typeof(int);
  235. case PythonOperationKind.Contains: return typeof(bool);
  236. case PythonOperationKind.GetEnumeratorForIteration: return typeof(KeyValuePair<IEnumerator, IDisposable>);
  237. case PythonOperationKind.CallSignatures: return typeof(IList<string>);
  238. case PythonOperationKind.Documentation: return typeof(string);
  239. }
  240. return typeof(object);
  241. }
  242. }
  243. public override int GetHashCode() {
  244. return base.GetHashCode() ^ _context.Binder.GetHashCode() ^ _operation.GetHashCode();
  245. }
  246. public override bool Equals(object obj) {
  247. PythonOperationBinder ob = obj as PythonOperationBinder;
  248. if (ob == null) {
  249. return false;
  250. }
  251. return ob._context.Binder == _context.Binder && base.Equals(obj);
  252. }
  253. public PythonContext/*!*/ Context {
  254. get {
  255. return _context;
  256. }
  257. }
  258. public override string ToString() {
  259. return "Python " + Operation;
  260. }
  261. #region IExpressionSerializable Members
  262. public Expression CreateExpression() {
  263. return Ast.Call(
  264. typeof(PythonOps).GetMethod("MakeOperationAction"),
  265. BindingHelpers.CreateBinderStateExpression(),
  266. AstUtils.Constant((int)Operation)
  267. );
  268. }
  269. #endregion
  270. }
  271. }