PageRenderTime 57ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/IronPython_Main/Languages/IronPython/IronPython/Runtime/Operations/PythonOps.cs

#
C# | 4560 lines | 3333 code | 813 blank | 414 comment | 946 complexity | 4de2c747f53fd5d597c3ab5c514ee4aa MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  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 !CLR2
  16. using System.Linq.Expressions;
  17. using System.Numerics;
  18. using Microsoft.Scripting.Ast;
  19. #else
  20. using Microsoft.Scripting.Ast;
  21. using Microsoft.Scripting.Math;
  22. using Complex = Microsoft.Scripting.Math.Complex64;
  23. #endif
  24. using System;
  25. using System.Collections;
  26. using System.Collections.Generic;
  27. using System.Diagnostics;
  28. using System.Dynamic;
  29. using System.IO;
  30. using System.Reflection;
  31. using System.Reflection.Emit;
  32. using System.Runtime.CompilerServices;
  33. using System.Runtime.InteropServices;
  34. using System.Text;
  35. using System.Threading;
  36. using Microsoft.Scripting;
  37. using Microsoft.Scripting.Actions;
  38. using Microsoft.Scripting.Generation;
  39. using Microsoft.Scripting.Hosting.Providers;
  40. using Microsoft.Scripting.Hosting.Shell;
  41. using Microsoft.Scripting.Runtime;
  42. using Microsoft.Scripting.Utils;
  43. using IronPython.Compiler;
  44. using IronPython.Hosting;
  45. using IronPython.Modules;
  46. using IronPython.Runtime.Binding;
  47. using IronPython.Runtime.Exceptions;
  48. using IronPython.Runtime.Types;
  49. #if !SILVERLIGHT
  50. using System.ComponentModel;
  51. #endif
  52. namespace IronPython.Runtime.Operations {
  53. /// <summary>
  54. /// Contains functions that are called directly from
  55. /// generated code to perform low-level runtime functionality.
  56. /// </summary>
  57. public static partial class PythonOps {
  58. #region Shared static data
  59. [ThreadStatic]
  60. private static List<object> InfiniteRepr;
  61. // The "current" exception on this thread that will be returned via sys.exc_info()
  62. [ThreadStatic]
  63. internal static Exception RawException;
  64. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  65. public static readonly PythonTuple EmptyTuple = PythonTuple.EMPTY;
  66. private static readonly Type[] _DelegateCtorSignature = new Type[] { typeof(object), typeof(IntPtr) };
  67. #endregion
  68. public static BigInteger MakeIntegerFromHex(string s) {
  69. return LiteralParser.ParseBigInteger(s, 16);
  70. }
  71. public static PythonDictionary MakeDict(int size) {
  72. return new PythonDictionary(size);
  73. }
  74. public static PythonDictionary MakeEmptyDict() {
  75. return new PythonDictionary(EmptyDictionaryStorage.Instance);
  76. }
  77. /// <summary>
  78. /// Creates a new dictionary extracting the keys and values from the
  79. /// provided data array. Keys/values are adjacent in the array with
  80. /// the value coming first.
  81. /// </summary>
  82. public static PythonDictionary MakeDictFromItems(params object[] data) {
  83. return new PythonDictionary(new CommonDictionaryStorage(data, false));
  84. }
  85. public static PythonDictionary MakeConstantDict(object items) {
  86. return new PythonDictionary((ConstantDictionaryStorage)items);
  87. }
  88. public static object MakeConstantDictStorage(params object[] data) {
  89. return new ConstantDictionaryStorage(new CommonDictionaryStorage(data, false));
  90. }
  91. public static SetCollection MakeSet(params object[] items) {
  92. return new SetCollection(items);
  93. }
  94. public static SetCollection MakeEmptySet() {
  95. return new SetCollection();
  96. }
  97. /// <summary>
  98. /// Creates a new dictionary extracting the keys and values from the
  99. /// provided data array. Keys/values are adjacent in the array with
  100. /// the value coming first.
  101. /// </summary>
  102. public static PythonDictionary MakeHomogeneousDictFromItems(object[] data) {
  103. return new PythonDictionary(new CommonDictionaryStorage(data, true));
  104. }
  105. public static bool IsCallable(CodeContext/*!*/ context, object o) {
  106. // This tells if an object can be called, but does not make a claim about the parameter list.
  107. // In 1.x, we could check for certain interfaces like ICallable*, but those interfaces were deprecated
  108. // in favor of dynamic sites.
  109. // This is difficult to infer because we'd need to simulate the entire callbinder, which can include
  110. // looking for [SpecialName] call methods and checking for a rule from IDynamicMetaObjectProvider. But even that wouldn't
  111. // be complete since sites require the argument list of the call, and we only have the instance here.
  112. // Thus check a dedicated IsCallable operator. This lets each object describe if it's callable.
  113. // Invoke Operator.IsCallable on the object.
  114. return PythonContext.GetContext(context).IsCallable(o);
  115. }
  116. public static bool UserObjectIsCallable(CodeContext/*!*/ context, object o) {
  117. object callFunc;
  118. return TryGetBoundAttr(context, o, "__call__", out callFunc) && callFunc != null;
  119. }
  120. public static bool IsTrue(object o) {
  121. return Converter.ConvertToBoolean(o);
  122. }
  123. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
  124. public static List<object> GetReprInfinite() {
  125. if (InfiniteRepr == null) {
  126. InfiniteRepr = new List<object>();
  127. }
  128. return InfiniteRepr;
  129. }
  130. [LightThrowing]
  131. internal static object LookupEncodingError(CodeContext/*!*/ context, string name) {
  132. Dictionary<string, object> errorHandlers = PythonContext.GetContext(context).ErrorHandlers;
  133. lock (errorHandlers) {
  134. if (errorHandlers.ContainsKey(name))
  135. return errorHandlers[name];
  136. else
  137. return LightExceptions.Throw(PythonOps.LookupError("unknown error handler name '{0}'", name));
  138. }
  139. }
  140. internal static void RegisterEncodingError(CodeContext/*!*/ context, string name, object handler) {
  141. Dictionary<string, object> errorHandlers = PythonContext.GetContext(context).ErrorHandlers;
  142. lock (errorHandlers) {
  143. if (!PythonOps.IsCallable(context, handler))
  144. throw PythonOps.TypeError("handler must be callable");
  145. errorHandlers[name] = handler;
  146. }
  147. }
  148. internal static PythonTuple LookupEncoding(CodeContext/*!*/ context, string encoding) {
  149. PythonContext.GetContext(context).EnsureEncodings();
  150. List<object> searchFunctions = PythonContext.GetContext(context).SearchFunctions;
  151. string normalized = encoding.ToLower().Replace(' ', '-');
  152. if (normalized.IndexOf(Char.MinValue) != -1) {
  153. throw PythonOps.TypeError("lookup string cannot contain null character");
  154. }
  155. lock (searchFunctions) {
  156. for (int i = 0; i < searchFunctions.Count; i++) {
  157. object res = PythonCalls.Call(context, searchFunctions[i], normalized);
  158. if (res != null) return (PythonTuple)res;
  159. }
  160. }
  161. throw PythonOps.LookupError("unknown encoding: {0}", encoding);
  162. }
  163. internal static void RegisterEncoding(CodeContext/*!*/ context, object search_function) {
  164. if (!PythonOps.IsCallable(context, search_function))
  165. throw PythonOps.TypeError("search_function must be callable");
  166. List<object> searchFunctions = PythonContext.GetContext(context).SearchFunctions;
  167. lock (searchFunctions) {
  168. searchFunctions.Add(search_function);
  169. }
  170. }
  171. internal static string GetPythonTypeName(object obj) {
  172. OldInstance oi = obj as OldInstance;
  173. if (oi != null) return oi._class._name.ToString();
  174. else return PythonTypeOps.GetName(obj);
  175. }
  176. public static string Repr(CodeContext/*!*/ context, object o) {
  177. if (o == null) return "None";
  178. string s;
  179. if ((s = o as string) != null) return StringOps.__repr__(s);
  180. if (o is int) return Int32Ops.__repr__((int)o);
  181. if (o is long) return ((long)o).ToString() + "L";
  182. // could be a container object, we need to detect recursion, but only
  183. // for our own built-in types that we're aware of. The user can setup
  184. // infinite recursion in their own class if they want.
  185. ICodeFormattable f = o as ICodeFormattable;
  186. if (f != null) {
  187. return f.__repr__(context);
  188. }
  189. PerfTrack.NoteEvent(PerfTrack.Categories.Temporary, "Repr " + o.GetType().FullName);
  190. return PythonContext.InvokeUnaryOperator(context, UnaryOperators.Repr, o) as string;
  191. }
  192. public static List<object> GetAndCheckInfinite(object o) {
  193. List<object> infinite = GetReprInfinite();
  194. foreach (object o2 in infinite) {
  195. if (o == o2) {
  196. return null;
  197. }
  198. }
  199. return infinite;
  200. }
  201. public static string ToString(object o) {
  202. return ToString(DefaultContext.Default, o);
  203. }
  204. public static string ToString(CodeContext/*!*/ context, object o) {
  205. string x = o as string;
  206. PythonType dt;
  207. OldClass oc;
  208. if (x != null) return x;
  209. if (o == null) return "None";
  210. if (o is double) return DoubleOps.__str__(context, (double)o);
  211. if ((dt = o as PythonType) != null) return dt.__repr__(DefaultContext.Default);
  212. if ((oc = o as OldClass) != null) return oc.ToString();
  213. object value = PythonContext.InvokeUnaryOperator(context, UnaryOperators.String, o);
  214. string ret = value as string;
  215. if (ret == null) {
  216. Extensible<string> es = value as Extensible<string>;
  217. if (es == null) {
  218. throw PythonOps.TypeError("expected str, got {0} from __str__", PythonTypeOps.GetName(value));
  219. }
  220. ret = es.Value;
  221. }
  222. return ret;
  223. }
  224. public static string FormatString(CodeContext/*!*/ context, string str, object data) {
  225. return new StringFormatter(context, str, data).Format();
  226. }
  227. public static string FormatUnicode(CodeContext/*!*/ context, string str, object data) {
  228. return new StringFormatter(context, str, data, true).Format();
  229. }
  230. public static object Plus(object o) {
  231. object ret;
  232. if (o is int) return o;
  233. else if (o is double) return o;
  234. else if (o is BigInteger) return o;
  235. else if (o is Complex) return o;
  236. else if (o is long) return o;
  237. else if (o is float) return o;
  238. else if (o is bool) return ScriptingRuntimeHelpers.Int32ToObject((bool)o ? 1 : 0);
  239. if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default, o, "__pos__", out ret) &&
  240. ret != NotImplementedType.Value) {
  241. return ret;
  242. }
  243. throw PythonOps.TypeError("bad operand type for unary +");
  244. }
  245. public static object Negate(object o) {
  246. if (o is int) return Int32Ops.Negate((int)o);
  247. else if (o is double) return DoubleOps.Negate((double)o);
  248. else if (o is long) return Int64Ops.Negate((long)o);
  249. else if (o is BigInteger) return BigIntegerOps.Negate((BigInteger)o);
  250. else if (o is Complex) return -(Complex)o;
  251. else if (o is float) return DoubleOps.Negate((float)o);
  252. else if (o is bool) return ScriptingRuntimeHelpers.Int32ToObject((bool)o ? -1 : 0);
  253. object ret;
  254. if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default, o, "__neg__", out ret) &&
  255. ret != NotImplementedType.Value) {
  256. return ret;
  257. }
  258. throw PythonOps.TypeError("bad operand type for unary -");
  259. }
  260. public static bool IsSubClass(PythonType/*!*/ c, PythonType/*!*/ typeinfo) {
  261. Assert.NotNull(c, typeinfo);
  262. if (c.OldClass != null) {
  263. return typeinfo.__subclasscheck__(c.OldClass);
  264. }
  265. return typeinfo.__subclasscheck__(c);
  266. }
  267. public static bool IsSubClass(CodeContext/*!*/ context, PythonType c, object typeinfo) {
  268. if (c == null) throw PythonOps.TypeError("issubclass: arg 1 must be a class");
  269. if (typeinfo == null) throw PythonOps.TypeError("issubclass: arg 2 must be a class");
  270. PythonTuple pt = typeinfo as PythonTuple;
  271. PythonContext pyContext = PythonContext.GetContext(context);
  272. if (pt != null) {
  273. // Recursively inspect nested tuple(s)
  274. foreach (object o in pt) {
  275. try {
  276. FunctionPushFrame(pyContext);
  277. if (IsSubClass(context, c, o)) {
  278. return true;
  279. }
  280. } finally {
  281. FunctionPopFrame();
  282. }
  283. }
  284. return false;
  285. }
  286. OldClass oc = typeinfo as OldClass;
  287. if (oc != null) {
  288. return c.IsSubclassOf(oc.TypeObject);
  289. }
  290. Type t = typeinfo as Type;
  291. if (t != null) {
  292. typeinfo = DynamicHelpers.GetPythonTypeFromType(t);
  293. }
  294. object bases;
  295. PythonType dt = typeinfo as PythonType;
  296. if (dt == null) {
  297. if (!PythonOps.TryGetBoundAttr(typeinfo, "__bases__", out bases)) {
  298. //!!! deal with classes w/ just __bases__ defined.
  299. throw PythonOps.TypeErrorForBadInstance("issubclass(): {0} is not a class nor a tuple of classes", typeinfo);
  300. }
  301. IEnumerator ie = PythonOps.GetEnumerator(bases);
  302. while (ie.MoveNext()) {
  303. PythonType baseType = ie.Current as PythonType;
  304. if (baseType == null) {
  305. OldClass ocType = ie.Current as OldClass;
  306. if (ocType == null) {
  307. continue;
  308. }
  309. baseType = ocType.TypeObject;
  310. }
  311. if (c.IsSubclassOf(baseType)) return true;
  312. }
  313. return false;
  314. }
  315. return IsSubClass(c, dt);
  316. }
  317. public static bool IsInstance(object o, PythonType typeinfo) {
  318. if (typeinfo.__instancecheck__(o)) {
  319. return true;
  320. }
  321. return IsInstanceDynamic(o, typeinfo, DynamicHelpers.GetPythonType(o));
  322. }
  323. public static bool IsInstance(CodeContext/*!*/ context, object o, PythonTuple typeinfo) {
  324. PythonContext pyContext = PythonContext.GetContext(context);
  325. foreach (object type in typeinfo) {
  326. try {
  327. PythonOps.FunctionPushFrame(pyContext);
  328. if (type is PythonType) {
  329. if (IsInstance(o, (PythonType)type)) {
  330. return true;
  331. }
  332. } else if (type is PythonTuple) {
  333. if (IsInstance(context, o, (PythonTuple)type)) {
  334. return true;
  335. }
  336. } else if (IsInstance(context, o, type)) {
  337. return true;
  338. }
  339. } finally {
  340. PythonOps.FunctionPopFrame();
  341. }
  342. }
  343. return false;
  344. }
  345. public static bool IsInstance(CodeContext/*!*/ context, object o, object typeinfo) {
  346. if (typeinfo == null) throw PythonOps.TypeError("isinstance: arg 2 must be a class, type, or tuple of classes and types");
  347. PythonTuple tt = typeinfo as PythonTuple;
  348. if (tt != null) {
  349. return IsInstance(context, o, tt);
  350. }
  351. if (typeinfo is OldClass) {
  352. // old instances are strange - they all share a common type
  353. // of instance but they can "be subclasses" of other
  354. // OldClass's. To check their types we need the actual
  355. // instance.
  356. OldInstance oi = o as OldInstance;
  357. if (oi != null) return oi._class.IsSubclassOf(typeinfo);
  358. }
  359. PythonType odt = DynamicHelpers.GetPythonType(o);
  360. if (IsSubClass(context, odt, typeinfo)) {
  361. return true;
  362. }
  363. return IsInstanceDynamic(o, typeinfo);
  364. }
  365. private static bool IsInstanceDynamic(object o, object typeinfo) {
  366. return IsInstanceDynamic(o, typeinfo, DynamicHelpers.GetPythonType(o));
  367. }
  368. private static bool IsInstanceDynamic(object o, object typeinfo, PythonType odt) {
  369. if (o is IPythonObject || o is OldInstance) {
  370. object cls;
  371. if (PythonOps.TryGetBoundAttr(o, "__class__", out cls) &&
  372. (!object.ReferenceEquals(odt, cls))) {
  373. return IsSubclassSlow(cls, typeinfo);
  374. }
  375. }
  376. return false;
  377. }
  378. private static bool IsSubclassSlow(object cls, object typeinfo) {
  379. Debug.Assert(typeinfo != null);
  380. if (cls == null) return false;
  381. // Same type
  382. if (cls.Equals(typeinfo)) {
  383. return true;
  384. }
  385. // Get bases
  386. object bases;
  387. if (!PythonOps.TryGetBoundAttr(cls, "__bases__", out bases)) {
  388. return false; // no bases, cannot be subclass
  389. }
  390. PythonTuple tbases = bases as PythonTuple;
  391. if (tbases == null) {
  392. return false; // not a tuple, cannot be subclass
  393. }
  394. foreach (object baseclass in tbases) {
  395. if (IsSubclassSlow(baseclass, typeinfo)) return true;
  396. }
  397. return false;
  398. }
  399. public static object OnesComplement(object o) {
  400. if (o is int) return ~(int)o;
  401. if (o is long) return ~(long)o;
  402. if (o is BigInteger) return ~((BigInteger)o);
  403. if (o is bool) return ScriptingRuntimeHelpers.Int32ToObject((bool)o ? -2 : -1);
  404. object ret;
  405. if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default, o, "__invert__", out ret) &&
  406. ret != NotImplementedType.Value)
  407. return ret;
  408. throw PythonOps.TypeError("bad operand type for unary ~");
  409. }
  410. public static bool Not(object o) {
  411. return !IsTrue(o);
  412. }
  413. public static object Is(object x, object y) {
  414. return x == y ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  415. }
  416. public static bool IsRetBool(object x, object y) {
  417. return x == y;
  418. }
  419. public static object IsNot(object x, object y) {
  420. return x != y ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  421. }
  422. public static bool IsNotRetBool(object x, object y) {
  423. return x != y;
  424. }
  425. internal delegate T MultiplySequenceWorker<T>(T self, int count);
  426. /// <summary>
  427. /// Wraps up all the semantics of multiplying sequences so that all of our sequences
  428. /// don't duplicate the same logic. When multiplying sequences we need to deal with
  429. /// only multiplying by valid sequence types (ints, not floats), support coercion
  430. /// to integers if the type supports it, not multiplying by None, and getting the
  431. /// right semantics for multiplying by negative numbers and 1 (w/ and w/o subclasses).
  432. ///
  433. /// This function assumes that it is only called for case where count is not implicitly
  434. /// coercible to int so that check is skipped.
  435. /// </summary>
  436. internal static object MultiplySequence<T>(MultiplySequenceWorker<T> multiplier, T sequence, Index count, bool isForward) {
  437. if (isForward && count != null) {
  438. object ret;
  439. if (PythonTypeOps.TryInvokeBinaryOperator(DefaultContext.Default, count.Value, sequence, "__rmul__", out ret)) {
  440. if (ret != NotImplementedType.Value) return ret;
  441. }
  442. }
  443. int icount = GetSequenceMultiplier(sequence, count.Value);
  444. if (icount < 0) icount = 0;
  445. return multiplier(sequence, icount);
  446. }
  447. internal static int GetSequenceMultiplier(object sequence, object count) {
  448. int icount;
  449. if (!Converter.TryConvertToIndex(count, out icount)) {
  450. PythonTuple pt = null;
  451. if (count is OldInstance || !DynamicHelpers.GetPythonType(count).IsSystemType) {
  452. pt = Builtin.TryCoerce(DefaultContext.Default, count, sequence) as PythonTuple;
  453. }
  454. if (pt == null || !Converter.TryConvertToIndex(pt[0], out icount)) {
  455. throw TypeError("can't multiply sequence by non-int of type '{0}'", PythonTypeOps.GetName(count));
  456. }
  457. }
  458. return icount;
  459. }
  460. public static object Equal(CodeContext/*!*/ context, object x, object y) {
  461. PythonContext pc = PythonContext.GetContext(context);
  462. return pc.EqualSite.Target(pc.EqualSite, x, y);
  463. }
  464. public static bool EqualRetBool(object x, object y) {
  465. //TODO just can't seem to shake these fast paths
  466. if (x is int && y is int) { return ((int)x) == ((int)y); }
  467. if (x is string && y is string) { return ((string)x).Equals((string)y); }
  468. return DynamicHelpers.GetPythonType(x).EqualRetBool(x, y);
  469. }
  470. public static bool EqualRetBool(CodeContext/*!*/ context, object x, object y) {
  471. // TODO: use context
  472. //TODO just can't seem to shake these fast paths
  473. if (x is int && y is int) { return ((int)x) == ((int)y); }
  474. if (x is string && y is string) { return ((string)x).Equals((string)y); }
  475. return DynamicHelpers.GetPythonType(x).EqualRetBool(x, y);
  476. }
  477. public static int Compare(object x, object y) {
  478. return Compare(DefaultContext.Default, x, y);
  479. }
  480. public static int Compare(CodeContext/*!*/ context, object x, object y) {
  481. if (x == y) return 0;
  482. return DynamicHelpers.GetPythonType(x).Compare(x, y);
  483. }
  484. public static object CompareEqual(int res) {
  485. return res == 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  486. }
  487. public static object CompareNotEqual(int res) {
  488. return res == 0 ? ScriptingRuntimeHelpers.False : ScriptingRuntimeHelpers.True;
  489. }
  490. public static object CompareGreaterThan(int res) {
  491. return res > 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  492. }
  493. public static object CompareGreaterThanOrEqual(int res) {
  494. return res >= 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  495. }
  496. public static object CompareLessThan(int res) {
  497. return res < 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  498. }
  499. public static object CompareLessThanOrEqual(int res) {
  500. return res <= 0 ? ScriptingRuntimeHelpers.True : ScriptingRuntimeHelpers.False;
  501. }
  502. public static bool CompareTypesEqual(CodeContext/*!*/ context, object x, object y) {
  503. if (x == null && y == null) return true;
  504. if (x == null) return false;
  505. if (y == null) return false;
  506. if (DynamicHelpers.GetPythonType(x) == DynamicHelpers.GetPythonType(y)) {
  507. // avoid going to the ID dispenser if we have the same types...
  508. return x == y;
  509. }
  510. return PythonOps.CompareTypesWorker(context, false, x, y) == 0;
  511. }
  512. public static bool CompareTypesNotEqual(CodeContext/*!*/ context, object x, object y) {
  513. return PythonOps.CompareTypesWorker(context, false, x, y) != 0;
  514. }
  515. public static bool CompareTypesGreaterThan(CodeContext/*!*/ context, object x, object y) {
  516. return PythonOps.CompareTypes(context, x, y) > 0;
  517. }
  518. public static bool CompareTypesLessThan(CodeContext/*!*/ context, object x, object y) {
  519. return PythonOps.CompareTypes(context, x, y) < 0;
  520. }
  521. public static bool CompareTypesGreaterThanOrEqual(CodeContext/*!*/ context, object x, object y) {
  522. return PythonOps.CompareTypes(context, x, y) >= 0;
  523. }
  524. public static bool CompareTypesLessThanOrEqual(CodeContext/*!*/ context, object x, object y) {
  525. return PythonOps.CompareTypes(context, x, y) <= 0;
  526. }
  527. public static int CompareTypesWorker(CodeContext/*!*/ context, bool shouldWarn, object x, object y) {
  528. if (x == null && y == null) return 0;
  529. if (x == null) return -1;
  530. if (y == null) return 1;
  531. string name1, name2;
  532. int diff;
  533. if (DynamicHelpers.GetPythonType(x) != DynamicHelpers.GetPythonType(y)) {
  534. if (shouldWarn && PythonContext.GetContext(context).PythonOptions.WarnPython30) {
  535. PythonOps.Warn(context, PythonExceptions.DeprecationWarning, "comparing unequal types not supported in 3.x");
  536. }
  537. if (x.GetType() == typeof(OldInstance)) {
  538. name1 = ((OldInstance)x)._class.Name;
  539. if (y.GetType() == typeof(OldInstance)) {
  540. name2 = ((OldInstance)y)._class.Name;
  541. } else {
  542. // old instances are always less than new-style classes
  543. return -1;
  544. }
  545. } else if (y.GetType() == typeof(OldInstance)) {
  546. // old instances are always less than new-style classes
  547. return 1;
  548. } else {
  549. name1 = PythonTypeOps.GetName(x);
  550. name2 = PythonTypeOps.GetName(y);
  551. }
  552. diff = String.CompareOrdinal(name1, name2);
  553. if (diff == 0) {
  554. // if the types are different but have the same name compare based upon their types.
  555. diff = (int)(IdDispenser.GetId(DynamicHelpers.GetPythonType(x)) - IdDispenser.GetId(DynamicHelpers.GetPythonType(y)));
  556. }
  557. } else {
  558. diff = (int)(IdDispenser.GetId(x) - IdDispenser.GetId(y));
  559. }
  560. if (diff < 0) return -1;
  561. if (diff == 0) return 0;
  562. return 1;
  563. }
  564. public static int CompareTypes(CodeContext/*!*/ context, object x, object y) {
  565. return CompareTypesWorker(context, true, x, y);
  566. }
  567. public static object GreaterThanHelper(CodeContext/*!*/ context, object self, object other) {
  568. return InternalCompare(context, PythonOperationKind.GreaterThan, self, other);
  569. }
  570. public static object LessThanHelper(CodeContext/*!*/ context, object self, object other) {
  571. return InternalCompare(context, PythonOperationKind.LessThan, self, other);
  572. }
  573. public static object GreaterThanOrEqualHelper(CodeContext/*!*/ context, object self, object other) {
  574. return InternalCompare(context, PythonOperationKind.GreaterThanOrEqual, self, other);
  575. }
  576. public static object LessThanOrEqualHelper(CodeContext/*!*/ context, object self, object other) {
  577. return InternalCompare(context, PythonOperationKind.LessThanOrEqual, self, other);
  578. }
  579. internal static object InternalCompare(CodeContext/*!*/ context, PythonOperationKind op, object self, object other) {
  580. object ret;
  581. if (PythonTypeOps.TryInvokeBinaryOperator(context, self, other, Symbols.OperatorToSymbol(op), out ret))
  582. return ret;
  583. return NotImplementedType.Value;
  584. }
  585. public static int CompareToZero(object value) {
  586. double val;
  587. if (Converter.TryConvertToDouble(value, out val)) {
  588. if (val > 0) return 1;
  589. if (val < 0) return -1;
  590. return 0;
  591. }
  592. throw PythonOps.TypeErrorForBadInstance("an integer is required (got {0})", value);
  593. }
  594. public static int CompareArrays(object[] data0, int size0, object[] data1, int size1) {
  595. int size = Math.Min(size0, size1);
  596. for (int i = 0; i < size; i++) {
  597. int c = PythonOps.Compare(data0[i], data1[i]);
  598. if (c != 0) return c;
  599. }
  600. if (size0 == size1) return 0;
  601. return size0 > size1 ? +1 : -1;
  602. }
  603. public static int CompareArrays(object[] data0, int size0, object[] data1, int size1, IComparer comparer) {
  604. int size = Math.Min(size0, size1);
  605. for (int i = 0; i < size; i++) {
  606. int c = comparer.Compare(data0[i], data1[i]);
  607. if (c != 0) return c;
  608. }
  609. if (size0 == size1) return 0;
  610. return size0 > size1 ? +1 : -1;
  611. }
  612. public static bool ArraysEqual(object[] data0, int size0, object[] data1, int size1) {
  613. if (size0 != size1) {
  614. return false;
  615. }
  616. for (int i = 0; i < size0; i++) {
  617. if (data0[i] != null) {
  618. if (!EqualRetBool(data0[i], data1[i])) {
  619. return false;
  620. }
  621. } else if (data1[i] != null) {
  622. return false;
  623. }
  624. }
  625. return true;
  626. }
  627. public static bool ArraysEqual(object[] data0, int size0, object[] data1, int size1, IEqualityComparer comparer) {
  628. if (size0 != size1) {
  629. return false;
  630. }
  631. for (int i = 0; i < size0; i++) {
  632. if (data0[i] != null) {
  633. if (!comparer.Equals(data0[i], data1[i])) {
  634. return false;
  635. }
  636. } else if (data1[i] != null) {
  637. return false;
  638. }
  639. }
  640. return true;
  641. }
  642. public static object PowerMod(CodeContext/*!*/ context, object x, object y, object z) {
  643. object ret;
  644. if (z == null) {
  645. return PythonContext.GetContext(context).Operation(PythonOperationKind.Power, x, y);
  646. }
  647. if (x is int && y is int && z is int) {
  648. ret = Int32Ops.Power((int)x, (int)y, (int)z);
  649. if (ret != NotImplementedType.Value) return ret;
  650. } else if (x is BigInteger) {
  651. ret = BigIntegerOps.Power((BigInteger)x, y, z);
  652. if (ret != NotImplementedType.Value) return ret;
  653. }
  654. if (x is Complex || y is Complex || z is Complex) {
  655. throw PythonOps.ValueError("complex modulo");
  656. }
  657. if (PythonTypeOps.TryInvokeTernaryOperator(context, x, y, z, "__pow__", out ret)) {
  658. if (ret != NotImplementedType.Value) {
  659. return ret;
  660. } else if (!IsNumericObject(y) || !IsNumericObject(z)) {
  661. // special error message in this case...
  662. throw TypeError("pow() 3rd argument not allowed unless all arguments are integers");
  663. }
  664. }
  665. throw PythonOps.TypeErrorForBinaryOp("power with modulus", x, y);
  666. }
  667. public static long Id(object o) {
  668. return IdDispenser.GetId(o);
  669. }
  670. public static string HexId(object o) {
  671. return string.Format("0x{0:X16}", Id(o));
  672. }
  673. // For hash operators, it's essential that:
  674. // Cmp(x,y)==0 implies hash(x) == hash(y)
  675. //
  676. // Equality is a language semantic determined by the Python's numerical Compare() ops
  677. // in IronPython.Runtime.Operations namespaces.
  678. // For example, the CLR compares float(1.0) and int32(1) as different, but Python
  679. // compares them as equal. So Hash(1.0f) and Hash(1) must be equal.
  680. //
  681. // Python allows an equality relationship between int, double, BigInteger, and complex.
  682. // So each of these hash functions must be aware of their possible equality relationships
  683. // and hash appropriately.
  684. //
  685. // Types which differ in hashing from .NET have __hash__ functions defined in their
  686. // ops classes which do the appropriate hashing.
  687. public static int Hash(CodeContext/*!*/ context, object o) {
  688. return PythonContext.Hash(o);
  689. }
  690. public static object Hex(object o) {
  691. if (o is int) return Int32Ops.__hex__((int)o);
  692. else if (o is BigInteger) return BigIntegerOps.__hex__((BigInteger)o);
  693. object hex;
  694. if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default,
  695. o,
  696. "__hex__",
  697. out hex)) {
  698. if (!(hex is string) && !(hex is ExtensibleString))
  699. throw PythonOps.TypeError("hex expected string type as return, got '{0}'", PythonTypeOps.GetName(hex));
  700. return hex;
  701. }
  702. throw TypeError("hex() argument cannot be converted to hex");
  703. }
  704. public static object Oct(object o) {
  705. if (o is int) {
  706. return Int32Ops.__oct__((int)o);
  707. } else if (o is BigInteger) {
  708. return BigIntegerOps.__oct__((BigInteger)o);
  709. }
  710. object octal;
  711. if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default,
  712. o,
  713. "__oct__",
  714. out octal)) {
  715. if (!(octal is string) && !(octal is ExtensibleString))
  716. throw PythonOps.TypeError("hex expected string type as return, got '{0}'", PythonTypeOps.GetName(octal));
  717. return octal;
  718. }
  719. throw TypeError("oct() argument cannot be converted to octal");
  720. }
  721. public static int Length(object o) {
  722. string s = o as string;
  723. if (s != null) {
  724. return s.Length;
  725. }
  726. object[] os = o as object[];
  727. if (os != null) {
  728. return os.Length;
  729. }
  730. object len = PythonContext.InvokeUnaryOperator(DefaultContext.Default, UnaryOperators.Length, o, "len() of unsized object");
  731. int res;
  732. if (len is int) {
  733. res = (int)len;
  734. } else {
  735. res = Converter.ConvertToInt32(len);
  736. }
  737. if (res < 0) {
  738. throw PythonOps.ValueError("__len__ should return >= 0, got {0}", res);
  739. }
  740. return res;
  741. }
  742. public static object CallWithContext(CodeContext/*!*/ context, object func, params object[] args) {
  743. return PythonCalls.Call(context, func, args);
  744. }
  745. /// <summary>
  746. /// Supports calling of functions that require an explicit 'this'
  747. /// Currently, we check if the function object implements the interface
  748. /// that supports calling with 'this'. If not, the 'this' object is dropped
  749. /// and a normal call is made.
  750. /// </summary>
  751. public static object CallWithContextAndThis(CodeContext/*!*/ context, object func, object instance, params object[] args) {
  752. // drop the 'this' and make the call
  753. return CallWithContext(context, func, args);
  754. }
  755. public static object ToPythonType(PythonType dt) {
  756. if (dt != null) {
  757. return ((object)dt.OldClass) ?? ((object)dt);
  758. }
  759. return null;
  760. }
  761. public static object CallWithArgsTupleAndContext(CodeContext/*!*/ context, object func, object[] args, object argsTuple) {
  762. PythonTuple tp = argsTuple as PythonTuple;
  763. if (tp != null) {
  764. object[] nargs = new object[args.Length + tp.__len__()];
  765. for (int i = 0; i < args.Length; i++) nargs[i] = args[i];
  766. for (int i = 0; i < tp.__len__(); i++) nargs[i + args.Length] = tp[i];
  767. return CallWithContext(context, func, nargs);
  768. }
  769. List allArgs = PythonOps.MakeEmptyList(args.Length + 10);
  770. allArgs.AddRange(args);
  771. IEnumerator e = PythonOps.GetEnumerator(argsTuple);
  772. while (e.MoveNext()) allArgs.AddNoLock(e.Current);
  773. return CallWithContext(context, func, allArgs.GetObjectArray());
  774. }
  775. [Obsolete("Use ObjectOpertaions instead")]
  776. public static object CallWithArgsTupleAndKeywordDictAndContext(CodeContext/*!*/ context, object func, object[] args, string[] names, object argsTuple, object kwDict) {
  777. IDictionary kws = kwDict as IDictionary;
  778. if (kws == null && kwDict != null) throw PythonOps.TypeError("argument after ** must be a dictionary");
  779. if ((kws == null || kws.Count == 0) && names.Length == 0) {
  780. List<object> largs = new List<object>(args);
  781. if (argsTuple != null) {
  782. foreach (object arg in PythonOps.GetCollection(argsTuple))
  783. largs.Add(arg);
  784. }
  785. return CallWithContext(context, func, largs.ToArray());
  786. } else {
  787. List<object> largs;
  788. if (argsTuple != null && args.Length == names.Length) {
  789. PythonTuple tuple = argsTuple as PythonTuple;
  790. if (tuple == null) tuple = new PythonTuple(argsTuple);
  791. largs = new List<object>(tuple);
  792. largs.AddRange(args);
  793. } else {
  794. largs = new List<object>(args);
  795. if (argsTuple != null) {
  796. largs.InsertRange(args.Length - names.Length, PythonTuple.Make(argsTuple));
  797. }
  798. }
  799. List<string> lnames = new List<string>(names);
  800. if (kws != null) {
  801. IDictionaryEnumerator ide = kws.GetEnumerator();
  802. while (ide.MoveNext()) {
  803. lnames.Add((string)ide.Key);
  804. largs.Add(ide.Value);
  805. }
  806. }
  807. return PythonCalls.CallWithKeywordArgs(context, func, largs.ToArray(), lnames.ToArray());
  808. }
  809. }
  810. public static object CallWithKeywordArgs(CodeContext/*!*/ context, object func, object[] args, string[] names) {
  811. return PythonCalls.CallWithKeywordArgs(context, func, args, names);
  812. }
  813. public static object CallWithArgsTuple(object func, object[] args, object argsTuple) {
  814. PythonTuple tp = argsTuple as PythonTuple;
  815. if (tp != null) {
  816. object[] nargs = new object[args.Length + tp.__len__()];
  817. for (int i = 0; i < args.Length; i++) nargs[i] = args[i];
  818. for (int i = 0; i < tp.__len__(); i++) nargs[i + args.Length] = tp[i];
  819. return PythonCalls.Call(func, nargs);
  820. }
  821. List allArgs = PythonOps.MakeEmptyList(args.Length + 10);
  822. allArgs.AddRange(args);
  823. IEnumerator e = PythonOps.GetEnumerator(argsTuple);
  824. while (e.MoveNext()) allArgs.AddNoLock(e.Current);
  825. return PythonCalls.Call(func, allArgs.GetObjectArray());
  826. }
  827. public static object GetIndex(CodeContext/*!*/ context, object o, object index) {
  828. PythonContext pc = PythonContext.GetContext(context);
  829. return pc.GetIndexSite.Target(pc.GetIndexSite, o, index);
  830. }
  831. public static bool TryGetBoundAttr(object o, string name, out object ret) {
  832. return TryGetBoundAttr(DefaultContext.Default, o, name, out ret);
  833. }
  834. public static void SetAttr(CodeContext/*!*/ context, object o, string name, object value) {
  835. PythonContext.GetContext(context).SetAttr(context, o, name, value);
  836. }
  837. public static bool TryGetBoundAttr(CodeContext/*!*/ context, object o, string name, out object ret) {
  838. return DynamicHelpers.GetPythonType(o).TryGetBoundAttr(context, o, name, out ret);
  839. }
  840. public static void DeleteAttr(CodeContext/*!*/ context, object o, string name) {
  841. PythonContext.GetContext(context).DeleteAttr(context, o, name);
  842. }
  843. public static bool HasAttr(CodeContext/*!*/ context, object o, string name) {
  844. object dummy;
  845. try {
  846. return TryGetBoundAttr(context, o, name, out dummy);
  847. } catch (SystemExitException) {
  848. throw;
  849. } catch (KeyboardInterruptException) {
  850. // we don't catch ThreadAbortException because it will
  851. // automatically re-throw on it's own.
  852. throw;
  853. } catch {
  854. return false;
  855. }
  856. }
  857. public static object GetBoundAttr(CodeContext/*!*/ context, object o, string name) {
  858. object ret;
  859. if (!DynamicHelpers.GetPythonType(o).TryGetBoundAttr(context, o, name, out ret)) {
  860. if (o is OldClass) {
  861. throw PythonOps.AttributeError("type object '{0}' has no attribute '{1}'",
  862. ((OldClass)o).Name, name);
  863. } else {
  864. throw PythonOps.AttributeError("'{0}' object has no attribute '{1}'", PythonTypeOps.GetName(o), name);
  865. }
  866. }
  867. return ret;
  868. }
  869. public static void ObjectSetAttribute(CodeContext/*!*/ context, object o, string name, object value) {
  870. if (!DynamicHelpers.GetPythonType(o).TrySetNonCustomMember(context, o, name, value))
  871. throw AttributeErrorForMissingOrReadonly(context, DynamicHelpers.GetPythonType(o), name);
  872. }
  873. public static void ObjectDeleteAttribute(CodeContext/*!*/ context, object o, string name) {
  874. if (!DynamicHelpers.GetPythonType(o).TryDeleteNonCustomMember(context, o, name)) {
  875. throw AttributeErrorForMissingOrReadonly(context, DynamicHelpers.GetPythonType(o), name);
  876. }
  877. }
  878. public static object ObjectGetAttribute(CodeContext/*!*/ context, object o, string name) {
  879. OldClass oc = o as OldClass;
  880. if (oc != null) {
  881. return oc.GetMember(context, name);
  882. }
  883. object value;
  884. if (DynamicHelpers.GetPythonType(o).TryGetNonCustomMember(context, o, name, out value)) {
  885. return value;
  886. }
  887. throw PythonOps.AttributeErrorForObjectMissingAttribute(o, name);
  888. }
  889. internal static IList<string> GetStringMemberList(IPythonMembersList pyMemList) {
  890. List<string> res = new List<string>();
  891. foreach (object o in pyMemList.GetMemberNames(DefaultContext.Default)) {
  892. if (o is string) {
  893. res.Add((string)o);
  894. }
  895. }
  896. return res;
  897. }
  898. public static IList<object> GetAttrNames(CodeContext/*!*/ context, object o) {
  899. IPythonMembersList pyMemList = o as IPythonMembersList;
  900. if (pyMemList != null) {
  901. return pyMemList.GetMemberNames(context);
  902. }
  903. IMembersList memList = o as IMembersList;
  904. if (memList != null) {
  905. return new List(memList.GetMemberNames());
  906. }
  907. IPythonObject po = o as IPythonObject;
  908. if (po != null) {
  909. return po.PythonType.GetMemberNames(context, o);
  910. }
  911. List res = DynamicHelpers.GetPythonType(o).GetMemberNames(context, o);
  912. #if !SILVERLIGHT
  913. if (o != null && Microsoft.Scripting.ComInterop.ComBinder.IsComObject(o)) {
  914. foreach (string name in Microsoft.Scripting.ComInterop.ComBinder.GetDynamicMemberNames(o)) {
  915. if (!res.Contains(name)) {
  916. res.AddNoLock(name);
  917. }
  918. }
  919. }
  920. #endif
  921. return res;
  922. }
  923. /// <summary>
  924. /// Called from generated code emitted by NewTypeMaker.
  925. /// </summary>
  926. public static void CheckInitializedAttribute(object o, object self, string name) {
  927. if (o == Uninitialized.Instance) {
  928. throw PythonOps.AttributeError("'{0}' object has no attribute '{1}'",
  929. PythonTypeOps.GetName(self),
  930. name);
  931. }
  932. }
  933. public static object GetUserSlotValue(CodeContext/*!*/ context, PythonTypeUserDescriptorSlot slot, object instance, PythonType type) {
  934. return slot.GetValue(context, instance, type);
  935. }
  936. /// <summary>
  937. /// Handles the descriptor protocol for user-defined objects that may implement __get__
  938. /// </summary>
  939. public static object GetUserDescriptor(object o, object instance, object context) {
  940. if (o is IPythonObject) {
  941. // slow, but only encountred for user defined descriptors.
  942. PerfTrack.NoteEvent(PerfTrack.Categories.DictInvoke, "__get__");
  943. object ret;
  944. if (PythonContext.TryInvokeTernaryOperator(DefaultContext.Default,
  945. TernaryOperators.GetDescriptor,
  946. o,
  947. instance,
  948. context,
  949. out ret)) {
  950. return ret;
  951. }
  952. }
  953. return o;
  954. }
  955. /// <summary>
  956. /// Handles the descriptor protocol for user-defined objects that may implement __set__
  957. /// </summary>
  958. public static bool TrySetUserDescriptor(object o, object instance, object value) {
  959. if (o != null && o.GetType() == typeof(OldInstance)) return false; // only new-style classes have descriptors
  960. // slow, but only encountred for user defined descriptors.
  961. PerfTrack.NoteEvent(PerfTrack.Categories.DictInvoke, "__set__");
  962. object dummy;
  963. return PythonContext.TryInvokeTernaryOperator(DefaultContext.Default,
  964. TernaryOperators.SetDescriptor,
  965. o,
  966. instance,
  967. value,
  968. out dummy);
  969. }
  970. /// <summary>
  971. /// Handles the descriptor protocol for user-defined objects that may implement __delete__
  972. /// </summary>
  973. public static bool TryDeleteUserDescriptor(object o, object instance) {
  974. if (o != null && o.GetType() == typeof(OldInstance)) return false; // only new-style classes can have descriptors
  975. // slow, but only encountred for user defined descriptors.
  976. PerfTrack.NoteEvent(PerfTrack.Categories.DictInvoke, "__delete__");
  977. object dummy;
  978. return PythonTypeOps.TryInvokeBinaryOperator(DefaultContext.Default,
  979. o,
  980. instance,
  981. "__delete__",
  982. out dummy);
  983. }
  984. public static object Invoke(CodeContext/*!*/ context, object target, string name, params object[] args) {
  985. return PythonCalls.Call(context, PythonOps.GetBoundAttr(context, target, name), args);
  986. }
  987. public static Delegate CreateDynamicDelegate(DynamicMethod meth, Type delegateT

Large files files are truncated, but you can click here to view the full file