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

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

https://bitbucket.org/williamybs/uidipythontool
C# | 287 lines | 219 code | 44 blank | 24 comment | 134 complexity | 4c1834220fe9148d569b3f761f05f198 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.Runtime.CompilerServices;
  23. using Microsoft.Scripting.Generation;
  24. using Microsoft.Scripting.Runtime;
  25. using Microsoft.Scripting.Utils;
  26. using IronPython.Runtime.Operations;
  27. namespace IronPython.Runtime.Binding {
  28. using Ast = Expression;
  29. using AstUtils = Microsoft.Scripting.Ast.Utils;
  30. class PythonUnaryOperationBinder : UnaryOperationBinder, IPythonSite, IExpressionSerializable {
  31. private readonly PythonContext/*!*/ _context;
  32. public PythonUnaryOperationBinder(PythonContext/*!*/ context, ExpressionType operation)
  33. : base(operation) {
  34. _context = context;
  35. }
  36. public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion) {
  37. return PythonProtocol.Operation(this, target, errorSuggestion);
  38. }
  39. public override int GetHashCode() {
  40. return base.GetHashCode() ^ _context.Binder.GetHashCode();
  41. }
  42. public override bool Equals(object obj) {
  43. PythonUnaryOperationBinder ob = obj as PythonUnaryOperationBinder;
  44. if (ob == null) {
  45. return false;
  46. }
  47. return ob._context.Binder == _context.Binder && base.Equals(obj);
  48. }
  49. public override T BindDelegate<T>(CallSite<T> site, object[] args) {
  50. switch (Operation) {
  51. case ExpressionType.Negate:
  52. if (CompilerHelpers.GetType(args[0]) == typeof(int)) {
  53. if (typeof(T) == typeof(Func<CallSite, object, object>)) {
  54. return (T)(object)new Func<CallSite, object, object>(IntNegate);
  55. }
  56. }
  57. break;
  58. case ExpressionType.IsFalse:
  59. if (args[0] == null) {
  60. if (typeof(T) == typeof(Func<CallSite, object, bool>)) {
  61. return (T)(object)new Func<CallSite, object, bool>(NoneIsFalse);
  62. }
  63. } else if (args[0].GetType() == typeof(string)) {
  64. if (typeof(T) == typeof(Func<CallSite, object, bool>)) {
  65. return (T)(object)new Func<CallSite, object, bool>(StringIsFalse);
  66. }
  67. } else if (args[0].GetType() == typeof(bool)) {
  68. if (typeof(T) == typeof(Func<CallSite, object, bool>)) {
  69. return (T)(object)new Func<CallSite, object, bool>(BoolIsFalse);
  70. }
  71. } else if (args[0].GetType() == typeof(List)) {
  72. if (typeof(T) == typeof(Func<CallSite, object, bool>)) {
  73. return (T)(object)new Func<CallSite, object, bool>(ListIsFalse);
  74. }
  75. } else if (args[0].GetType() == typeof(PythonTuple)) {
  76. if (typeof(T) == typeof(Func<CallSite, object, bool>)) {
  77. return (T)(object)new Func<CallSite, object, bool>(TupleIsFalse);
  78. }
  79. } else if (args[0].GetType() == typeof(int)) {
  80. if (typeof(T) == typeof(Func<CallSite, object, bool>)) {
  81. return (T)(object)new Func<CallSite, object, bool>(IntIsFalse);
  82. }
  83. }
  84. break;
  85. case ExpressionType.Not:
  86. if (args[0] == null) {
  87. if (typeof(T) == typeof(Func<CallSite, object, object>)) {
  88. return (T)(object)new Func<CallSite, object, object>(NoneNot);
  89. }
  90. } else if (args[0].GetType() == typeof(string)) {
  91. if (typeof(T) == typeof(Func<CallSite, object, object>)) {
  92. return (T)(object)new Func<CallSite, object, object>(StringNot);
  93. }
  94. } else if (args[0].GetType() == typeof(bool)) {
  95. if (typeof(T) == typeof(Func<CallSite, object, object>)) {
  96. return (T)(object)new Func<CallSite, object, object>(BoolNot);
  97. }
  98. } else if (args[0].GetType() == typeof(List)) {
  99. if (typeof(T) == typeof(Func<CallSite, object, object>)) {
  100. return (T)(object)new Func<CallSite, object, object>(ListNot);
  101. }
  102. } else if (args[0].GetType() == typeof(PythonTuple)) {
  103. if (typeof(T) == typeof(Func<CallSite, object, object>)) {
  104. return (T)(object)new Func<CallSite, object, object>(TupleNot);
  105. }
  106. } else if (args[0].GetType() == typeof(int)) {
  107. if (typeof(T) == typeof(Func<CallSite, object, object>)) {
  108. return (T)(object)new Func<CallSite, object, object>(IntNot);
  109. }
  110. }
  111. break;
  112. }
  113. return base.BindDelegate(site, args);
  114. }
  115. private object IntNegate(CallSite site, object value) {
  116. if (value is int) {
  117. return Int32Ops.Negate((int)value);
  118. }
  119. return ((CallSite<Func<CallSite, object, object>>)site).Update(site, value);
  120. }
  121. private bool StringIsFalse(CallSite site, object value) {
  122. string strVal = value as string;
  123. if (strVal != null) {
  124. return strVal.Length == 0;
  125. } else if (value == null) {
  126. // improve perf of sites just polymorphic on str & None
  127. return true;
  128. }
  129. return ((CallSite<Func<CallSite, object, bool>>)site).Update(site, value);
  130. }
  131. private bool ListIsFalse(CallSite site, object value) {
  132. if (value != null && value.GetType() == typeof(List)) {
  133. return ((List)value).Count == 0;
  134. } else if (value == null) {
  135. // improve perf of sites just polymorphic on list & None
  136. return true;
  137. }
  138. return ((CallSite<Func<CallSite, object, bool>>)site).Update(site, value);
  139. }
  140. private bool NoneIsFalse(CallSite site, object value) {
  141. if (value == null) {
  142. return true;
  143. }
  144. return ((CallSite<Func<CallSite, object, bool>>)site).Update(site, value);
  145. }
  146. private bool IntIsFalse(CallSite site, object value) {
  147. if (value is int) {
  148. return (int)value == 0;
  149. } else if (value == null) {
  150. // improve perf of sites just polymorphic on int & None
  151. return true;
  152. }
  153. return ((CallSite<Func<CallSite, object, bool>>)site).Update(site, value);
  154. }
  155. private bool TupleIsFalse(CallSite site, object value) {
  156. if (value != null && value.GetType() == typeof(PythonTuple)) {
  157. return ((PythonTuple)value).Count == 0;
  158. } else if (value == null) {
  159. // improve perf of sites just polymorphic on tuple & None
  160. return true;
  161. }
  162. return ((CallSite<Func<CallSite, object, bool>>)site).Update(site, value);
  163. }
  164. private bool BoolIsFalse(CallSite site, object value) {
  165. if (value is bool) {
  166. return !(bool)value;
  167. } else if (value == null) {
  168. // improve perf of sites just polymorphic on bool & None
  169. return true;
  170. }
  171. return ((CallSite<Func<CallSite, object, bool>>)site).Update(site, value);
  172. }
  173. private object StringNot(CallSite site, object value) {
  174. string strVal = value as string;
  175. if (strVal != null) {
  176. return strVal.Length == 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  177. } else if (value == null) {
  178. // improve perf of sites just polymorphic on str & None
  179. return true;
  180. }
  181. return ((CallSite<Func<CallSite, object, object>>)site).Update(site, value);
  182. }
  183. private object ListNot(CallSite site, object value) {
  184. if (value != null && value.GetType() == typeof(List)) {
  185. return ((List)value).Count == 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  186. } else if (value == null) {
  187. // improve perf of sites just polymorphic on list & None
  188. return true;
  189. }
  190. return ((CallSite<Func<CallSite, object, object>>)site).Update(site, value);
  191. }
  192. private object NoneNot(CallSite site, object value) {
  193. if (value == null) {
  194. return ScriptingRuntimeHelpers.True;
  195. }
  196. return ((CallSite<Func<CallSite, object, object>>)site).Update(site, value);
  197. }
  198. private object TupleNot(CallSite site, object value) {
  199. if (value != null && value.GetType() == typeof(PythonTuple)) {
  200. return ((PythonTuple)value).Count == 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  201. } else if (value == null) {
  202. // improve perf of sites just polymorphic on tuple & None
  203. return true;
  204. }
  205. return ((CallSite<Func<CallSite, object, object>>)site).Update(site, value);
  206. }
  207. private object BoolNot(CallSite site, object value) {
  208. if (value is bool) {
  209. return !(bool)value ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  210. } else if (value == null) {
  211. // improve perf of sites just polymorphic on bool & None
  212. return true;
  213. }
  214. return ((CallSite<Func<CallSite, object, object>>)site).Update(site, value);
  215. }
  216. private object IntNot(CallSite site, object value) {
  217. if (value is int) {
  218. return (int)value == 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  219. } else if (value == null) {
  220. // improve perf of sites just polymorphic on int & None
  221. return true;
  222. }
  223. return ((CallSite<Func<CallSite, object, object>>)site).Update(site, value);
  224. }
  225. public PythonContext/*!*/ Context {
  226. get {
  227. return _context;
  228. }
  229. }
  230. public override string ToString() {
  231. return "PythonUnary " + Operation;
  232. }
  233. #region IExpressionSerializable Members
  234. public Expression CreateExpression() {
  235. return Ast.Call(
  236. typeof(PythonOps).GetMethod("MakeUnaryOperationAction"),
  237. BindingHelpers.CreateBinderStateExpression(),
  238. AstUtils.Constant(Operation)
  239. );
  240. }
  241. #endregion
  242. }
  243. }