PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/IronPython/Runtime/Binding/PythonUnaryOperationBinder.cs

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