PageRenderTime 63ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/IronPython_2_6/Src/IronPython/Runtime/Operations/PythonOps.cs

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

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