PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 1ms

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

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

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