PageRenderTime 82ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  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.Min(length - 1, -1);
  987. }
  988. } else if (ostart >= length) {
  989. ostart = ostep > 0 ? length : length - 1;
  990. }
  991. }
  992. if (stop == null) {
  993. ostop = ostep > 0 ? length : -1;
  994. } else {
  995. ostop = Converter.ConvertToIndex(stop);
  996. if (ostop < 0) {
  997. ostop += length;
  998. if (ostop < 0) {
  999. ostop = Math.Min(length, -1);
  1000. }
  1001. } else if (ostop > length) {
  1002. ostop = length;
  1003. }
  1004. }
  1005. ocount = ostep > 0 ? (ostop - ostart + ostep - 1) / ostep
  1006. : (ostop - ostart + ostep + 1) / ostep;
  1007. }
  1008. public static int FixIndex(int v, int len) {
  1009. if (v < 0) {
  1010. v += len;
  1011. if (v < 0) {
  1012. throw PythonOps.IndexError("index out of range: {0}", v - len);
  1013. }
  1014. } else if (v >= len) {
  1015. throw PythonOps.IndexError("index out of range: {0}", v);
  1016. }
  1017. return v;
  1018. }
  1019. public static void InitializeForFinalization(CodeContext/*!*/ context, object newObject) {
  1020. IWeakReferenceable iwr = newObject as IWeakReferenceable;
  1021. Debug.Assert(iwr != null);
  1022. InstanceFinalizer nif = new InstanceFinalizer(context, newObject);
  1023. iwr.SetFinalizer(new WeakRefTracker(nif, nif));
  1024. }
  1025. private static object FindMetaclass(CodeContext/*!*/ context, PythonTuple bases, IAttributesCollection dict) {
  1026. // If dict['__metaclass__'] exists, it is used.
  1027. object ret;
  1028. if (dict.TryGetValue(Symbols.MetaClass, out ret) && ret != null) return ret;
  1029. // Otherwise, if there is at least one base class, its metaclass is used
  1030. for (int i = 0; i < bases.__len__(); i++) {
  1031. if (!(bases[i] is OldClass)) return DynamicHelpers.GetPythonType(bases[i]);
  1032. }
  1033. // Otherwise, if there's a global variable named __metaclass__, it is used.
  1034. if (context.GlobalScope.TryLookupName(Symbols.MetaClass, out ret) && ret != null) {
  1035. return ret;
  1036. }
  1037. //Otherwise, the classic metaclass (types.ClassType) is used.
  1038. return TypeCache.OldInstance;
  1039. }
  1040. public static object MakeClass(CodeContext/*!*/ context, string name, object[] bases, string selfNames, CallTarget0 body) {
  1041. CodeContext bodyContext = (CodeContext)body();
  1042. IAttributesCollection vars = bodyContext.Scope.Dict;
  1043. return MakeClass(context, name, bases, selfNames, vars);
  1044. }
  1045. internal static object MakeClass(CodeContext context, string name, object[] bases, string selfNames, IAttributesCollection vars) {
  1046. foreach (object dt in bases) {
  1047. if (dt is TypeGroup) {
  1048. object[] newBases = new object[bases.Length];
  1049. for (int i = 0; i < bases.Length; i++) {
  1050. TypeGroup tc = bases[i] as TypeGroup;
  1051. if (tc != null) {
  1052. Type nonGenericType;
  1053. if (!tc.TryGetNonGenericType(out nonGenericType)) {
  1054. throw PythonOps.TypeError("cannot derive from open generic types " + Builtin.repr(context, tc).ToString());
  1055. }
  1056. newBases[i] = DynamicHelpers.GetPythonTypeFromType(nonGenericType);
  1057. } else {
  1058. newBases[i] = bases[i];
  1059. }
  1060. }
  1061. bases = newBases;
  1062. break;
  1063. }
  1064. }
  1065. PythonTuple tupleBases = PythonTuple.MakeTuple(bases);
  1066. object metaclass = FindMetaclass(context, tupleBases, vars);
  1067. if (metaclass == TypeCache.OldInstance)
  1068. return new OldClass(name, tupleBases, vars, selfNames);
  1069. // eg:
  1070. // def foo(*args): print args
  1071. // __metaclass__ = foo
  1072. // class bar: pass
  1073. // calls our function...
  1074. PythonContext pc = PythonContext.GetContext(context);
  1075. return pc.MetaClassCallSite.Target(
  1076. pc.MetaClassCallSite,
  1077. context,
  1078. metaclass,
  1079. name,
  1080. tupleBases,
  1081. vars
  1082. );
  1083. }
  1084. /// <summary>
  1085. /// Python runtime helper for raising assertions. Used by AssertStatement.
  1086. /// </summary>
  1087. /// <param name="msg">Object representing the assertion message</param>
  1088. public static void RaiseAssertionError(object msg) {
  1089. if (msg == null) {
  1090. throw PythonOps.AssertionError(String.Empty, ArrayUtils.EmptyObjects);
  1091. } else {
  1092. string message = PythonOps.ToString(msg);
  1093. throw PythonOps.AssertionError("{0}", new object[] { message });
  1094. }
  1095. }
  1096. /// <summary>
  1097. /// Python runtime helper to create instance of Python List object.
  1098. /// </summary>
  1099. /// <returns>New instance of List</returns>
  1100. public static List MakeList() {
  1101. return new List();
  1102. }
  1103. /// <summary>
  1104. /// Python runtime helper to create a populated instance of Python List object.
  1105. /// </summary>
  1106. public static List MakeList(params object[] items) {
  1107. return new List(items);
  1108. }
  1109. /// <summary>
  1110. /// Python runtime helper to create a populated instance of Python List object w/o
  1111. /// copying the array contents.
  1112. /// </summary>
  1113. [NoSideEffects]
  1114. public static List MakeListNoCopy(params object[] items) {
  1115. return List.FromArrayNoCopy(items);
  1116. }
  1117. /// <summary>
  1118. /// Python runtime helper to create a populated instance of Python List object.
  1119. ///
  1120. /// List is populated by arbitrary user defined object.
  1121. /// </summary>
  1122. public static List MakeListFromSequence(object sequence) {
  1123. return new List(sequence);
  1124. }
  1125. /// <summary>
  1126. /// Python runtime helper to create an instance of Python List object.
  1127. ///
  1128. /// List has the initial provided capacity.
  1129. /// </summary>
  1130. [NoSideEffects]
  1131. public static List MakeEmptyList(int capacity) {
  1132. return new List(capacity);
  1133. }
  1134. [NoSideEffects]
  1135. public static List MakeEmptyListFromCode() {
  1136. return List.FromArrayNoCopy(ArrayUtils.EmptyObjects);
  1137. }
  1138. /// <summary>
  1139. /// Python runtime helper to create an instance of Tuple
  1140. /// </summary>
  1141. /// <param name="items"></param>
  1142. /// <returns></returns>
  1143. [NoSideEffects]
  1144. public static PythonTuple MakeTuple(params object[] items) {
  1145. return PythonTuple.MakeTuple(items);
  1146. }
  1147. /// <summary>
  1148. /// Python runtime helper to create an instance of Tuple
  1149. /// </summary>
  1150. /// <param name="items"></param>
  1151. [NoSideEffects]
  1152. public static PythonTuple MakeTupleFromSequence(object items) {
  1153. return PythonTuple.Make(items);
  1154. }
  1155. /// <summary>
  1156. /// Python Runtime Helper for enumerator unpacking (tuple assignments, ...)
  1157. /// Creates enumerator from the input parameter e, and then extracts
  1158. /// expected number of values, returning them as array
  1159. /// </summary>
  1160. /// <param name="e">object to enumerate</param>
  1161. /// <param name="expected">expected number of objects to extract from the enumerator</param>
  1162. /// <returns>
  1163. /// array of objects (.Lengh == expected) if exactly expected objects are in the enumerator.
  1164. /// Otherwise throws exception
  1165. /// </returns>
  1166. public static object[] GetEnumeratorValues(CodeContext/*!*/ context, object e, int expected) {
  1167. IEnumerator ie = PythonOps.GetEnumeratorForUnpack(context, e);
  1168. int count = 0;
  1169. object[] values = new object[expected];
  1170. while (count < expected) {
  1171. if (!ie.MoveNext()) {
  1172. throw PythonOps.ValueErrorForUnpackMismatch(expected, count);
  1173. }
  1174. values[count] = ie.Current;
  1175. count++;
  1176. }
  1177. if (ie.MoveNext()) {
  1178. throw PythonOps.ValueErrorForUnpackMismatch(expected, count + 1);
  1179. }
  1180. return values;
  1181. }
  1182. /// <summary>
  1183. /// Python runtime helper to create instance of Slice object
  1184. /// </summary>
  1185. /// <param name="start">Start of the slice.</param>
  1186. /// <param name="stop">End of the slice.</param>
  1187. /// <param name="step">Step of the slice.</param>
  1188. /// <returns>Slice</returns>
  1189. public static Slice MakeSlice(object start, object stop, object step) {
  1190. return new Slice(start, stop, step);
  1191. }
  1192. #region Standard I/O support
  1193. public static void Write(CodeContext/*!*/ context, object f, string text) {
  1194. PythonContext pc = PythonContext.GetContext(context);
  1195. if (f == null) {
  1196. f = pc.SystemStandardOut;
  1197. }
  1198. if (f == null || f == Uninitialized.Instance) {
  1199. throw PythonOps.RuntimeError("lost sys.std_out");
  1200. }
  1201. PythonFile pf = f as PythonFile;
  1202. if (pf != null) {
  1203. // avoid spinning up a site in the normal case
  1204. pf.write(text);
  1205. return;
  1206. }
  1207. pc.WriteCallSite.Target(
  1208. pc.WriteCallSite,
  1209. context,
  1210. GetBoundAttr(context, f, Symbols.ConsoleWrite),
  1211. text
  1212. );
  1213. }
  1214. private static object ReadLine(CodeContext/*!*/ context, object f) {
  1215. if (f == null || f == Uninitialized.Instance) throw PythonOps.RuntimeError("lost sys.std_in");
  1216. return PythonOps.Invoke(context, f, Symbols.ConsoleReadLine);
  1217. }
  1218. public static void WriteSoftspace(CodeContext/*!*/ context, object f) {
  1219. if (CheckSoftspace(f)) {
  1220. SetSoftspace(f, RuntimeHelpers.False);
  1221. Write(context, f, " ");
  1222. }
  1223. }
  1224. public static void SetSoftspace(object f, object value) {
  1225. PythonOps.SetAttr(DefaultContext.Default, f, Symbols.Softspace, value);
  1226. }
  1227. public static bool CheckSoftspace(object f) {
  1228. PythonFile pf = f as PythonFile;
  1229. if (pf != null) {
  1230. // avoid spinning up a site in the common case
  1231. return pf.softspace;
  1232. }
  1233. object result;
  1234. if (PythonOps.TryGetBoundAttr(f, Symbols.Softspace, out result)) {
  1235. return PythonOps.IsTrue(result);
  1236. }
  1237. return false;
  1238. }
  1239. // Must stay here for now because libs depend on it.
  1240. public static void Print(CodeContext/*!*/ context, object o) {
  1241. PrintWithDest(context, PythonContext.GetContext(context).SystemStandardOut, o);
  1242. }
  1243. public static void PrintNoNewline(CodeContext/*!*/ context, object o) {
  1244. PrintWithDestNoNewline(context, PythonContext.GetContext(context).SystemStandardOut, o);
  1245. }
  1246. public static void PrintWithDest(CodeContext/*!*/ context, object dest, object o) {
  1247. PrintWithDestNoNewline(context, dest, o);
  1248. Write(context, dest, "\n");
  1249. }
  1250. public static void PrintWithDestNoNewline(CodeContext/*!*/ context, object dest, object o) {
  1251. WriteSoftspace(context, dest);
  1252. Write(context, dest, o == null ? "None" : ToString(o));
  1253. }
  1254. public static object ReadLineFromSrc(CodeContext/*!*/ context, object src) {
  1255. return ReadLine(context, src);
  1256. }
  1257. /// <summary>
  1258. /// Prints newline into default standard output
  1259. /// </summary>
  1260. public static void PrintNewline(CodeContext/*!*/ context) {
  1261. PrintNewlineWithDest(context, PythonContext.GetContext(context).SystemStandardOut);
  1262. }
  1263. /// <summary>
  1264. /// Prints newline into specified destination. Sets softspace property to false.
  1265. /// </summary>
  1266. /// <param name="dest"></param>
  1267. public static void PrintNewlineWithDest(CodeContext/*!*/ context, object dest) {
  1268. PythonOps.Write(context, dest, "\n");
  1269. PythonOps.SetSoftspace(dest, RuntimeHelpers.False);
  1270. }
  1271. /// <summary>
  1272. /// Prints value into default standard output with Python comma semantics.
  1273. /// </summary>
  1274. /// <param name="o"></param>
  1275. public static void PrintComma(CodeContext/*!*/ context, object o) {
  1276. PrintCommaWithDest(context, PythonContext.GetContext(context).SystemStandardOut, o);
  1277. }
  1278. /// <summary>
  1279. /// Prints value into specified destination with Python comma semantics.
  1280. /// </summary>
  1281. /// <param name="dest"></param>
  1282. /// <param name="o"></param>
  1283. public static void PrintCommaWithDest(CodeContext/*!*/ context, object dest, object o) {
  1284. PythonOps.WriteSoftspace(context, dest);
  1285. string s = o == null ? "None" : PythonOps.ToString(o);
  1286. PythonOps.Write(context, dest, s);
  1287. PythonOps.SetSoftspace(dest, !s.EndsWith("\n"));
  1288. }
  1289. /// <summary>
  1290. /// Called from generated code when we are supposed to print an expression value
  1291. /// </summary>
  1292. public static void PrintExpressionValue(CodeContext/*!*/ context, object value) {
  1293. PythonContext pc = PythonContext.GetContext(context);
  1294. object dispHook = pc.GetSystemStateValue("displayhook");
  1295. pc.CallWithContext(context, dispHook, value);
  1296. }
  1297. #if !SILVERLIGHT
  1298. public static void PrintException(CodeContext/*!*/ context, Exception/*!*/ exception, IConsole console) {
  1299. PythonContext pc = PythonContext.GetContext(context);
  1300. object exceptHook = pc.GetSystemStateValue("excepthook");
  1301. BuiltinFunction bf = exceptHook as BuiltinFunction;
  1302. if (console != null && bf != null && bf.DeclaringType == typeof(SysModule) && bf.Name == "excepthook") {
  1303. // builtin except hook, display it to the console which may do nice coloring
  1304. console.WriteLine(pc.FormatException(exception), Style.Error);
  1305. } else {
  1306. // user defined except hook or no console
  1307. PythonTuple exInfo = GetExceptionInfoLocal(context, exception);
  1308. try {
  1309. PythonCalls.Call(context, exceptHook, exInfo[0], exInfo[1], exInfo[2]);
  1310. } catch (Exception e) {
  1311. PrintWithDest(context, pc.SystemStandardError, "Error in sys.excepthook:");
  1312. PrintWithDest(context, pc.SystemStandardError, pc.FormatException(e));
  1313. PrintNewlineWithDest(context, pc.SystemStandardError);
  1314. PrintWithDest(context, pc.SystemStandardError, "Original exception was:");
  1315. PrintWithDest(context, pc.SystemStandardError, pc.FormatException(exception));
  1316. }
  1317. }
  1318. }
  1319. #endif
  1320. #endregion
  1321. #region Import support
  1322. /// <summary>
  1323. /// Called from generated code for:
  1324. ///
  1325. /// import spam.eggs
  1326. /// </summary>
  1327. public static object ImportTop(CodeContext/*!*/ context, string fullName, int level) {
  1328. return Importer.Import(context, fullName, null, level);
  1329. }
  1330. /// <summary>
  1331. /// Python helper method called from generated code for:
  1332. ///
  1333. /// import spam.eggs as ham
  1334. /// </summary>
  1335. /// <param name="context"></param>
  1336. /// <param name="fullName"></param>
  1337. /// <returns></returns>
  1338. public static object ImportBottom(CodeContext/*!*/ context, string fullName, int level) {
  1339. object module = Importer.Import(context, fullName, null, level);
  1340. if (fullName.IndexOf('.') >= 0) {
  1341. // Extract bottom from the imported module chain
  1342. string[] parts = fullName.Split('.');
  1343. for (int i = 1; i < parts.Length; i++) {
  1344. module = PythonOps.GetBoundAttr(context, module, SymbolTable.StringToId(parts[i]));
  1345. }
  1346. }
  1347. return module;
  1348. }
  1349. /// <summary>
  1350. /// Called from generated code for:
  1351. ///
  1352. /// from spam import eggs1, eggs2
  1353. /// </summary>
  1354. public static object ImportWithNames(CodeContext/*!*/ context, string fullName, string[] names, int level) {
  1355. return Importer.Import(context, fullName, PythonTuple.MakeTuple(names), level);
  1356. }
  1357. /// <summary>
  1358. /// Imports one element from the module in the context of:
  1359. ///
  1360. /// from module import a, b, c, d
  1361. ///
  1362. /// Called repeatedly for all elements being imported (a, b, c, d above)
  1363. /// </summary>
  1364. public static object ImportFrom(CodeContext/*!*/ context, object module, string name) {
  1365. return Importer.ImportFrom(context, module, name);
  1366. }
  1367. /// <summary>
  1368. /// Called from generated code for:
  1369. ///
  1370. /// from spam import *
  1371. /// </summary>
  1372. public static void ImportStar(CodeContext/*!*/ context, string fullName, int level) {
  1373. object newmod = Importer.Import(context, fullName, PythonTuple.MakeTuple("*"), level);
  1374. Scope scope = newmod as Scope;
  1375. NamespaceTracker nt = newmod as NamespaceTracker;
  1376. PythonType pt = newmod as PythonType;
  1377. if (pt != null &&
  1378. !pt.UnderlyingSystemType.IsEnum &&
  1379. (!pt.UnderlyingSystemType.IsAbstract || !pt.UnderlyingSystemType.IsSealed)) {
  1380. // from type import * only allowed on static classes (and enums)
  1381. throw PythonOps.ImportError("no module named {0}", pt.Name);
  1382. }
  1383. IEnumerator exports;
  1384. object all;
  1385. bool filterPrivates = false;
  1386. // look for __all__, if it's defined then use that to get the attribute names,
  1387. // otherwise get all the names and filter out members starting w/ _'s.
  1388. if (PythonOps.TryGetBoundAttr(context, newmod, Symbols.All, out all)) {
  1389. exports = PythonOps.GetEnumerator(all);
  1390. } else {
  1391. exports = PythonOps.GetAttrNames(context, newmod).GetEnumerator();
  1392. filterPrivates = true;
  1393. }
  1394. // iterate through the names and populate the scope with the values.
  1395. while (exports.MoveNext()) {
  1396. string name = exports.Current as string;
  1397. if (name == null) {
  1398. throw PythonOps.TypeErrorForNonStringAttribute();
  1399. } else if (filterPrivates && name.Length > 0 && name[0] == '_') {
  1400. continue;
  1401. }
  1402. SymbolId fieldId = SymbolTable.StringToId(name);
  1403. // we special case several types to avoid one-off code gen of dynamic sites
  1404. if (scope != null) {
  1405. context.Scope.SetName(fieldId, scope.Dict[fieldId]);
  1406. } else if (nt != null) {
  1407. object value = ReflectedPackageOps.GetCustomMember(context, nt, name);
  1408. if (value != OperationFailed.Value) {
  1409. context.Scope.SetName(fieldId, value);
  1410. }
  1411. } else if (pt != null) {
  1412. PythonTypeSlot pts;
  1413. object value;
  1414. if (pt.TryResolveSlot(context, fieldId, out pts) &&
  1415. pts.TryGetValue(context, null, pt, out value)) {
  1416. context.Scope.SetName(fieldId, value);
  1417. }
  1418. } else {
  1419. // not a known type, we'll do use a site to do the get...
  1420. context.Scope.SetName(fieldId, PythonOps.GetBoundAttr(context, newmod, fieldId));
  1421. }
  1422. }
  1423. }
  1424. #endregion
  1425. #region Exec
  1426. /// <summary>
  1427. /// Unqualified exec statement support.
  1428. /// A Python helper which will be called for the statement:
  1429. ///
  1430. /// exec code
  1431. /// </summary>
  1432. public static void UnqualifiedExec(CodeContext/*!*/ context, object code) {
  1433. IAttributesCollection locals = null;
  1434. IAttributesCollection globals = null;
  1435. // if the user passes us a tuple we'll extract the 3 values out of it
  1436. PythonTuple codeTuple = code as PythonTuple;
  1437. if (codeTuple != null && codeTuple.__len__() > 0 && codeTuple.__len__() <= 3) {
  1438. code = codeTuple[0];
  1439. if (codeTuple.__len__() > 1 && codeTuple[1] != null) {
  1440. globals = codeTuple[1] as IAttributesCollection;
  1441. if (globals == null) throw PythonOps.TypeError("globals must be dictionary or none");
  1442. }
  1443. if (codeTuple.__len__() > 2 && codeTuple[2] != null) {
  1444. locals = codeTuple[2] as IAttributesCollection;
  1445. if (locals == null) throw PythonOps.TypeError("locals must be dictionary or none");
  1446. } else {
  1447. locals = globals;
  1448. }
  1449. }
  1450. QualifiedExec(context, code, globals, locals);
  1451. }
  1452. /// <summary>
  1453. /// Qualified exec statement support,
  1454. /// Python helper which will be called for the statement:
  1455. ///
  1456. /// exec code in globals [, locals ]
  1457. /// </summary>
  1458. public static void QualifiedExec(CodeContext/*!*/ context, object code, IAttributesCollection globals, object locals) {
  1459. PythonFile pf;
  1460. Stream cs;
  1461. var pythonContext = PythonContext.GetContext(context);
  1462. bool noLineFeed = true;
  1463. // TODO: use ContentProvider?
  1464. if ((pf = code as PythonFile) != null) {
  1465. List lines = pf.readlines();
  1466. StringBuilder fullCode = new StringBuilder();
  1467. for (int i = 0; i < lines.__len__(); i++) {
  1468. fullCode.Append(lines[i]);
  1469. }
  1470. code = fullCode.ToString();
  1471. } else if ((cs = code as Stream) != null) {
  1472. using (StreamReader reader = new StreamReader(cs)) { // TODO: encoding?
  1473. code = reader.ReadToEnd();
  1474. }
  1475. noLineFeed = false;
  1476. }
  1477. string strCode = code as string;
  1478. if (strCode != null) {
  1479. SourceUnit source;
  1480. if (noLineFeed) {
  1481. source = pythonContext.CreateSourceUnit(new NoLineFeedSourceContentProvider(strCode), null, SourceCodeKind.Statements);
  1482. } else {
  1483. source = pythonContext.CreateSnippet(strCode, SourceCodeKind.Statements);
  1484. }
  1485. PythonCompilerOptions compilerOptions = Builtin.GetDefaultCompilerOptions(context, true, 0);
  1486. // do interpretation only on strings -- not on files, streams, or code objects
  1487. code = new FunctionCode(pythonContext.CompileSourceCode(source, compilerOptions, ThrowingErrorSink.Default, true));
  1488. }
  1489. FunctionCode fc = code as FunctionCode;
  1490. if (fc == null) {
  1491. throw PythonOps.TypeError("arg 1 must be a string, file, Stream, or code object");
  1492. }
  1493. if (locals == null) locals = globals;
  1494. if (globals == null) globals = new PythonDictionary(new GlobalScopeDictionaryStorage(context.Scope));
  1495. if (locals != null && PythonOps.IsMappingType(context, locals) != RuntimeHelpers.True) {
  1496. throw PythonOps.TypeError("exec: arg 3 must be mapping or None");
  1497. }
  1498. Scope execScope = Builtin.GetExecEvalScope(context, globals, Builtin.GetAttrLocals(context, locals), true, false);
  1499. fc.Call(execScope);
  1500. }
  1501. #endregion
  1502. public static IEnumerator GetEnumeratorForIteration(CodeContext/*!*/ context, object enumerable) {
  1503. IEnumerator enumerator;
  1504. if (!TryGetEnumerator(context, enumerable, out enumerator)) {
  1505. throw PythonOps.TypeError(
  1506. "iteration over non-sequence of type {0}",
  1507. PythonOps.Repr(context, DynamicHelpers.GetPythonType(enumerable))
  1508. );
  1509. }
  1510. return enumerator;
  1511. }
  1512. internal static bool TryGetEnumerator(CodeContext/*!*/ context, object enumerable, out IEnumerator enumerator) {
  1513. string str = enumerable as string;
  1514. if (str != null) {
  1515. enumerator = StringOps.StringEnumerator(str);
  1516. return true;
  1517. }
  1518. IEnumerable enumer = enumerable as IEnumerable;
  1519. if (enumer != null) {
  1520. enumerator = enumer.GetEnumerator();
  1521. return true;
  1522. }
  1523. enumerator = enumerable as IEnumerator;
  1524. if (enumerator != null) {
  1525. return true;
  1526. }
  1527. IEnumerable ie;
  1528. if (!PythonContext.GetContext(context).TryConvertToIEnumerable(enumerable, out ie)) {
  1529. return false;
  1530. }
  1531. enumerator = ie.GetEnumerator();
  1532. return true;
  1533. }
  1534. #region Exception handling
  1535. // The semantics here are:
  1536. // 1. Each thread has a "current exception", which is returned as a tuple by sys.exc_info().
  1537. // 2. The current exception is set on encountering an except block, even if the except block doesn't
  1538. // match the exception.
  1539. // 3. Each function on exit (either via exception, return, or yield) will restore the "current exception"
  1540. // to the value it had on function-entry.
  1541. //
  1542. // So common codegen would be:
  1543. //
  1544. // function() {
  1545. // $save = SaveCurrentException();
  1546. // try {
  1547. // def foo():
  1548. // try:
  1549. // except:
  1550. // SetCurrentException($exception)
  1551. // <except body>
  1552. //
  1553. // finally {
  1554. // RestoreCurrentException($save)
  1555. // }
  1556. // Called at the start of the except handlers to set the current exception.
  1557. public static object SetCurrentException(CodeContext/*!*/ context, Exception/*!*/ clrException) {
  1558. Assert.NotNull(clrException);
  1559. // we need to extract before we check because ThreadAbort.ExceptionState is cleared after
  1560. // we reset the abort.
  1561. object res = PythonExceptions.ToPython(clrException);
  1562. #if !SILVERLIGHT
  1563. // Check for thread abort exceptions.
  1564. // This is necessary to be able to catch python's KeyboardInterrupt exceptions.
  1565. // CLR restrictions require that this must be called from within a catch block. This gets
  1566. // called even if we aren't going to handle the exception - we'll just reset the abort
  1567. ThreadAbortException tae = clrException as ThreadAbortException;
  1568. if (tae != null && tae.ExceptionState is KeyboardInterruptException) {
  1569. Thread.ResetAbort();
  1570. }
  1571. #endif
  1572. RawException = clrException;
  1573. return res;
  1574. }
  1575. public static void BuildExceptionInfo(CodeContext/*!*/ context, Exception clrException) {
  1576. ExceptionHelpers.AssociateDynamicStackFrames(clrException);
  1577. GetExceptionInfo(context);
  1578. ClearDynamicStackFrames();
  1579. }
  1580. // Clear the current exception. Most callers should restore the exception.
  1581. // This is mainly for sys.exc_clear()
  1582. public static void ClearCurrentException() {
  1583. RestoreCurrentException(null);
  1584. }
  1585. // Called by code-gen to save it. Codegen just needs to pass this back to RestoreCurrentException.
  1586. public static Exception SaveCurrentException() {
  1587. return RawException;
  1588. }
  1589. // Called at function exit (like popping). Pass value from SaveCurrentException.
  1590. public static void RestoreCurrentException(Exception clrException) {
  1591. RawException = clrException;
  1592. }
  1593. public static object CheckException(object exception, object test) {
  1594. Debug.Assert(exception != null);
  1595. StringException strex;
  1596. ObjectException objex;
  1597. if (test is PythonTuple) {
  1598. // we handle multiple exceptions, we'll check them one at a time.
  1599. PythonTuple tt = test as PythonTuple;
  1600. for (int i = 0; i < tt.__len__(); i++) {
  1601. object res = CheckException(exception, tt[i]);
  1602. if (res != null) return res;
  1603. }
  1604. } else if ((strex = exception as StringException) != null) {
  1605. // catching a string
  1606. if (test.GetType() != typeof(string)) return null;
  1607. if (strex.Message == (string)test) {
  1608. if (strex.Value == null) return strex.Message;
  1609. return strex.Value;
  1610. }
  1611. return null;
  1612. } else if ((objex = exception as ObjectException) != null) {
  1613. if (PythonOps.IsSubClass(objex.Type, test)) {
  1614. return objex.Instance;
  1615. }
  1616. return null;
  1617. } else if (test is OldClass) {
  1618. if (PythonOps.IsInstance(exception, test)) {
  1619. // catching a Python type.
  1620. return exception;
  1621. }
  1622. } else if (test is PythonType) {
  1623. if (PythonOps.IsSubClass(test as PythonType, TypeCache.BaseException)) {
  1624. // catching a Python exception type explicitly.
  1625. if (PythonOps.IsInstance(exception, test)) return exception;
  1626. } else if (PythonOps.IsSubClass(test as PythonType, DynamicHelpers.GetPythonTypeFromType(typeof(Exception)))) {
  1627. // catching a CLR exception type explicitly.
  1628. Exception clrEx = PythonExceptions.ToClr(exception);
  1629. if (PythonOps.IsInstance(clrEx, test)) return clrEx;
  1630. }
  1631. }
  1632. return null;
  1633. }
  1634. private static TraceBack CreateTraceBack(Exception e) {
  1635. // user provided trace back
  1636. if (e.Data.Contains(typeof(TraceBack))) {
  1637. return (TraceBack)e.Data[typeof(TraceBack)];
  1638. }
  1639. DynamicStackFrame[] frames = RuntimeHelpers.GetDynamicStackFrames(e, false);
  1640. TraceBack tb = null;
  1641. for (int i = 0; i < frames.Length; i++) {
  1642. DynamicStackFrame frame = frames[i];
  1643. string name = frame.GetMethodName();
  1644. if (name.IndexOf('#') > 0) {
  1645. // dynamic method, strip the trailing id...
  1646. name = name.Substring(0, name.IndexOf('#'));
  1647. }
  1648. PythonFunction fx = new PythonFunction(frame.CodeContext, name, null, ArrayUtils.EmptyStrings, ArrayUtils.EmptyObjects, FunctionAttributes.None);
  1649. TraceBackFrame tbf = new TraceBackFrame(
  1650. new PythonDictionary(new GlobalScopeDictionaryStorage(frame.CodeContext.Scope)),
  1651. LocalScopeDictionaryStorage.GetDictionaryFromScope(frame.CodeContext.Scope),
  1652. fx.func_code);
  1653. fx.func_code.SetFilename(frame.GetFileName());
  1654. fx.func_code.SetLineNumber(frame.GetFileLineNumber());
  1655. tb = new TraceBack(tb, tbf);
  1656. tb.SetLine(frame.GetFileLineNumber());
  1657. }
  1658. e.Data[typeof(TraceBack)] = tb;
  1659. return tb;
  1660. }
  1661. /// <summary>
  1662. /// Get an exception tuple for the "current" exception. This is used for sys.exc_info()
  1663. /// </summary>
  1664. public static PythonTuple GetExceptionInfo(CodeContext/*!*/ context) {
  1665. return GetExceptionInfoLocal(context, RawException);
  1666. }
  1667. /// <summary>
  1668. /// Get an exception tuple for a given exception. This is like the inverse of MakeException.
  1669. /// </summary>
  1670. /// <param name="ex">the exception to create a tuple for.</param>
  1671. /// <returns>a tuple of (type, value, traceback)</returns>
  1672. /// <remarks>This is called directly by the With statement so that it can get an exception tuple
  1673. /// in its own private except handler without disturbing the thread-wide sys.exc_info(). </remarks>
  1674. public static PythonTuple/*!*/ GetExceptionInfoLocal(CodeContext/*!*/ context, Exception ex) {
  1675. if (ex == null) {
  1676. return PythonTuple.MakeTuple(null, null, null);
  1677. }
  1678. object pyExcep = PythonExceptions.ToPython(ex);
  1679. TraceBack tb = CreateTraceBack(ex);
  1680. PythonContext pc = PythonContext.GetContext(context);
  1681. pc.SystemExceptionTraceBack = tb;
  1682. StringException se = pyExcep as StringException;
  1683. if (se == null) {
  1684. object excType = PythonOps.GetBoundAttr(context, pyExcep, Symbols.Class);
  1685. pc.SystemExceptionType = excType;
  1686. pc.SystemExceptionValue = pyExcep;
  1687. return PythonTuple.MakeTuple(
  1688. excType,
  1689. pyExcep,
  1690. tb);
  1691. }
  1692. // string exceptions are special... there tuple looks
  1693. // like string, argument, traceback instead of
  1694. // type, instance, traceback
  1695. pc.SystemExceptionType = pyExcep;
  1696. pc.SystemExceptionValue = se.Value;
  1697. return PythonTuple.MakeTuple(
  1698. pyExcep,
  1699. se.Value,
  1700. tb);
  1701. }
  1702. /// <summary>
  1703. /// helper function for re-raised exceptions.
  1704. /// </summary>
  1705. public static Exception MakeRethrownException(CodeContext/*!*/ context) {
  1706. PythonTuple t = GetExceptionInfo(context);
  1707. Exception e = MakeException(context, t[0], t[1], t[2]);
  1708. ExceptionHelpers.UpdateForRethrow(e);
  1709. return e;
  1710. }
  1711. /// <summary>
  1712. /// helper function for non-re-raise exceptions.
  1713. ///
  1714. /// type is the type of exception to throw or an instance. If it
  1715. /// is an instance then value should be null.
  1716. ///
  1717. /// If type is a type then value can either be an instance of type,
  1718. /// a Tuple, or a single value. This case is handled by EC.CreateThrowable.
  1719. /// </summary>
  1720. public static Exception MakeException(CodeContext/*!*/ context, object type, object value, object traceback) {
  1721. Exception throwable;
  1722. PythonType pt;
  1723. if (type is Exception) {
  1724. throwable = type as Exception;
  1725. } else if (type is PythonExceptions.BaseException) {
  1726. throwable = PythonExceptions.ToClr(type);
  1727. } else if ((pt = type as PythonType) != null && typeof(PythonExceptions.BaseException).IsAssignableFrom(pt.UnderlyingSystemType)) {
  1728. throwable = PythonExceptions.CreateThrowableForRaise(context, pt, value);
  1729. } else if (type is string) {
  1730. PythonOps.Warn(context, PythonExceptions.DeprecationWarning, "raising a string exception is deprecated");
  1731. throwable = new StringException(type.ToString(), value);
  1732. } else if (type is OldClass) {
  1733. if (value == null) {
  1734. throwable = new OldInstanceException((OldInstance)PythonCalls.Call(context, type));
  1735. } else {
  1736. throwable = PythonExceptions.CreateThrowableForRaise(context, (OldClass)type, value);
  1737. }
  1738. } else if (type is OldInstance) {
  1739. throwable = new OldInstanceException((OldInstance)type);
  1740. } else {
  1741. throwable = MakeExceptionTypeError(type);
  1742. }
  1743. IDictionary dict = throwable.Data;
  1744. if (traceback != null) {
  1745. TraceBack tb = traceback as TraceBack;
  1746. if (tb == null) throw PythonOps.TypeError("traceback argument must be a traceback object");
  1747. dict[typeof(TraceBack)] = tb;
  1748. } else if (dict.Contains(typeof(TraceBack))) {
  1749. dict.Remove(typeof(TraceBack));
  1750. }
  1751. PerfTrack.NoteEvent(PerfTrack.Categories.Exceptions, throwable);
  1752. return throwable;
  1753. }
  1754. public static void ClearDynamicStackFrames() {
  1755. ExceptionHelpers.DynamicStackFrames = null;
  1756. }
  1757. public static List<DynamicStackFrame> GetAndClearDynamicStackFrames() {
  1758. List<DynamicStackFrame> res = ExceptionHelpers.DynamicStackFrames;
  1759. ClearDynamicStackFrames();
  1760. return res;
  1761. }
  1762. public static void SetDynamicStackFrames(List<DynamicStackFrame> frames) {
  1763. ExceptionHelpers.DynamicStackFrames = frames;
  1764. }
  1765. #endregion
  1766. public static string[] GetFunctionSignature(PythonFunction function) {
  1767. return new string[] { function.GetSignatureString() };
  1768. }
  1769. public static PythonDictionary CopyAndVerifyDictionary(PythonFunction function, IDictionary dict) {
  1770. foreach (object o in dict.Keys) {
  1771. if (!(o is string)) {
  1772. throw TypeError("{0}() keywords most be strings", function.__name__);
  1773. }
  1774. }
  1775. return new PythonDictionary(dict);
  1776. }
  1777. public static PythonDictionary CopyAndVerifyPythonDictionary(PythonFunction function, PythonDictionary dict) {
  1778. if (dict._storage.HasNonStringAttributes()) {
  1779. throw TypeError("{0}() keywords most be strings", function.__name__);
  1780. }
  1781. return new PythonDictionary(dict);
  1782. }
  1783. public static object ExtractDictionaryArgument(PythonFunction function, string name, int argCnt, IAttributesCollection dict) {
  1784. object val;
  1785. if (dict.TryGetObjectValue(name, out val)) {
  1786. dict.RemoveObjectKey(name);
  1787. return val;
  1788. }
  1789. throw PythonOps.TypeError("{0}() takes exactly {1} non-keyword arguments ({2} given)",
  1790. function.__name__,
  1791. function.NormalArgumentCount,
  1792. argCnt);
  1793. }
  1794. public static void AddDictionaryArgument(PythonFunction function, string name, object value, IAttributesCollection dict) {
  1795. if (dict.ContainsObjectKey(name)) {
  1796. throw MultipleKeywordArgumentError(function, name);
  1797. }
  1798. dict.AddObjectKey(name, value);
  1799. }
  1800. public static void VerifyUnduplicatedByPosition(PythonFunction function, string name, int position, int listlen) {
  1801. if (listlen > 0 && listlen > position) {
  1802. throw MultipleKeywordArgumentError(function, name);
  1803. }
  1804. }
  1805. public static List CopyAndVerifyParamsList(PythonFunction function, object list) {
  1806. return new List(list);
  1807. }
  1808. public static PythonTuple GetOrCopyParamsTuple(object input) {
  1809. if (input.GetType() == typeof(PythonTuple)) {
  1810. return (PythonTuple)input;
  1811. }
  1812. return PythonTuple.Make(input);
  1813. }
  1814. public static object ExtractParamsArgument(PythonFunction function, int argCnt, List list) {
  1815. if (list.__len__() != 0) {
  1816. return list.pop(0);
  1817. }
  1818. throw function.BadArgumentError(argCnt);
  1819. }
  1820. public static void AddParamsArguments(List list, params object[] args) {
  1821. for (int i = 0; i < args.Length; i++) {
  1822. list.insert(i, args[i]);
  1823. }
  1824. }
  1825. /// <summary>
  1826. /// Extracts an argument from either the dictionary or params
  1827. /// </summary>
  1828. public static object ExtractAnyArgument(PythonFunction function, string name, int argCnt, List list, IDictionary dict) {
  1829. object val;
  1830. if (dict.Contains(name)) {
  1831. if (list.__len__() != 0) {
  1832. throw MultipleKeywordArgumentError(function, name);
  1833. }
  1834. val = dict[name];
  1835. dict.Remove(name);
  1836. return val;
  1837. }
  1838. if (list.__len__() != 0) {
  1839. return list.pop(0);
  1840. }
  1841. if (function.ExpandDictPosition == -1 && dict.Count > 0) {
  1842. // python raises an error for extra splatted kw keys before missing arguments.
  1843. // therefore we check for this in the error case here.
  1844. foreach (string x in dict.Keys) {
  1845. bool found = false;
  1846. foreach (string y in function.ArgNames) {
  1847. if (x == y) {
  1848. found = true;
  1849. break;
  1850. }
  1851. }
  1852. if (!found) {
  1853. throw UnexpectedKeywordArgumentError(function, x);
  1854. }
  1855. }
  1856. }
  1857. throw BinderOps.TypeErrorForIncorrectArgumentCount(
  1858. function.__name__,
  1859. function.NormalArgumentCount,
  1860. function.Defaults.Length,
  1861. argCnt,
  1862. function.ExpandListPosition != -1,
  1863. dict.Count > 0);
  1864. }
  1865. public static object GetParamsValueOrDefault(PythonFunction function, int index, List extraArgs) {
  1866. if (extraArgs.__len__() > 0) {
  1867. return extraArgs.pop(0);
  1868. }
  1869. return function.Defaults[index];
  1870. }
  1871. public static object GetFunctionParameterValue(PythonFunction function, int index, string name, List extraArgs, IAttributesCollection dict) {
  1872. if (extraArgs != null && extraArgs.__len__() > 0) {
  1873. return extraArgs.pop(0);
  1874. }
  1875. object val;
  1876. if (dict != null && ((PythonDictionary)dict).TryRemoveValue(name, out val)) {
  1877. return val;
  1878. }
  1879. return function.Defaults[index];
  1880. }
  1881. public static void CheckParamsZero(PythonFunction function, List extraArgs) {
  1882. if (extraArgs.__len__() != 0) {
  1883. throw function.BadArgumentError(extraArgs.__len__() + function.NormalArgumentCount);
  1884. }
  1885. }
  1886. public static void CheckUserParamsZero(PythonFunction function, object sequence) {
  1887. int len = PythonOps.Length(sequence);
  1888. if(len != 0) {
  1889. throw function.BadArgumentError(len + function.NormalArgumentCount);
  1890. }
  1891. }
  1892. public static void CheckDictionaryZero(PythonFunction function, IDictionary dict) {
  1893. if (dict.Count != 0) {
  1894. IDictionaryEnumerator ie = dict.GetEnumerator();
  1895. ie.MoveNext();
  1896. throw UnexpectedKeywordArgumentError(function, (string)ie.Key);
  1897. }
  1898. }
  1899. public static bool CheckDictionaryMembers(IAttributesCollection dict, string[] names) {
  1900. if (dict.Count != names.Length) {
  1901. return false;
  1902. }
  1903. foreach (string name in names) {
  1904. if (!dict.ContainsKey(SymbolTable.StringToId(name))) {
  1905. return false;
  1906. }
  1907. }
  1908. return true;
  1909. }
  1910. /// <summary>
  1911. /// Creates a new array the values set to Uninitialized.Instance. The array
  1912. /// is large enough to hold for all of the slots allocated for the type and
  1913. /// its sub types.
  1914. /// </summary>
  1915. public static object[]/*!*/ InitializeUserTypeSlots(PythonType/*!*/ type) {
  1916. object[] res = new object[type.SlotCount];
  1917. for (int i = 0; i < res.Length; i++) {
  1918. res[i] = Uninitialized.Instance;
  1919. }
  1920. return res;
  1921. }
  1922. public static bool IsClsVisible(CodeContext/*!*/ context) {
  1923. PythonModule module = PythonContext.GetModule(context);
  1924. return module == null || module.ShowCls;
  1925. }
  1926. public static object GetInitMember(CodeContext/*!*/ context, PythonType type, object instance) {
  1927. object value;
  1928. bool res = type.TryGetNonCustomBoundMember(context, instance, Symbols.Init, out value);
  1929. Debug.Assert(res);
  1930. return value;
  1931. }
  1932. public static object GetInitSlotMember(CodeContext/*!*/ context, PythonType type, PythonTypeSlot slot, object instance) {
  1933. object value;
  1934. if (!slot.TryGetBoundValue(context, instance, type, out value)) {
  1935. throw PythonOps.TypeError("bad __init__");
  1936. }
  1937. return value;
  1938. }
  1939. public static object GetMixedMember(CodeContext/*!*/ context, PythonType type, object instance, SymbolId name) {
  1940. foreach (PythonType t in type.ResolutionOrder) {
  1941. if (t.IsOldClass) {
  1942. OldClass oc = (OldClass)ToPythonType(t);
  1943. object ret;
  1944. if (oc.__dict__._storage.TryGetValue(name, out ret)) {
  1945. if (instance != null) return oc.GetOldStyleDescriptor(context, ret, instance, oc);
  1946. return ret;
  1947. }
  1948. } else {
  1949. PythonTypeSlot dts;
  1950. if (t.TryLookupSlot(context, name, out dts)) {
  1951. object ret;
  1952. if (dts.TryGetBoundValue(context, instance, type, out ret)) {
  1953. return ret;
  1954. }
  1955. return dts;
  1956. }
  1957. }
  1958. }
  1959. throw AttributeErrorForMissingAttribute(type, name);
  1960. }
  1961. #region Slicing support
  1962. /// <summary>
  1963. /// Helper to determine if the value is a simple numeric type (int or big int or bool) - used for OldInstance
  1964. /// deprecated form of slicing.
  1965. /// </summary>
  1966. public static bool IsNumericObject(object value) {
  1967. return value is int || value is Extensible<int> || value is BigInteger || value is Extensible<BigInteger> || value is bool;
  1968. }
  1969. /// <summary>
  1970. /// Helper to determine if the type is a simple numeric type (int or big int or bool) - used for OldInstance
  1971. /// deprecated form of slicing.
  1972. /// </summary>
  1973. internal static bool IsNumericType(Type t) {
  1974. return IsNonExtensibleNumericType(t) ||
  1975. t.IsSubclassOf(typeof(Extensible<int>)) ||
  1976. t.IsSubclassOf(typeof(Extensible<BigInteger>));
  1977. }
  1978. /// <summary>
  1979. /// Helper to determine if the type is a simple numeric type (int or big int or bool) but not a subclass
  1980. /// </summary>
  1981. internal static bool IsNonExtensibleNumericType(Type t) {
  1982. return t == typeof(int) ||
  1983. t == typeof(bool) ||
  1984. t == typeof(BigInteger);
  1985. }
  1986. /// <summary>
  1987. /// For slicing. Fixes up a BigInteger and returns an integer w/ the length of the
  1988. /// object added if the value is negative.
  1989. /// </summary>
  1990. public static int NormalizeBigInteger(object self, BigInteger bi, ref Nullable<int> length) {
  1991. int val;
  1992. if (bi < BigInteger.Zero) {
  1993. GetLengthOnce(self, ref length);
  1994. if (bi.AsInt32(out val)) {
  1995. Debug.Assert(length.HasValue);
  1996. return val + length.Value;
  1997. } else {
  1998. return -1;
  1999. }
  2000. } else if (bi.AsInt32(out val)) {
  2001. return val;
  2002. }
  2003. return Int32.MaxValue;
  2004. }
  2005. /// <summary>
  2006. /// For slicing. Gets the length of the object, used to only get the length once.
  2007. /// </summary>
  2008. public static int GetLengthOnce(object self, ref Nullable<int> length) {
  2009. if (length != null) return length.Value;
  2010. length = PythonOps.Length(self);
  2011. return length.Value;
  2012. }
  2013. #endregion
  2014. public static ReflectedEvent.BoundEvent MakeBoundEvent(ReflectedEvent eventObj, object instance, Type type) {
  2015. return new ReflectedEvent.BoundEvent(eventObj, instance, DynamicHelpers.GetPythonTypeFromType(type));
  2016. }
  2017. /// <summary>
  2018. /// Helper method for DynamicSite rules that check the version of their dynamic object
  2019. /// TODO - Remove this method for more direct field accesses
  2020. /// </summary>
  2021. /// <param name="o"></param>
  2022. /// <param name="version"></param>
  2023. /// <returns></returns>
  2024. public static bool CheckTypeVersion(object o, int version) {
  2025. IPythonObject po = o as IPythonObject;
  2026. if (po == null) return false;
  2027. return po.PythonType.Version == version;
  2028. }
  2029. public static bool CheckSpecificTypeVersion(PythonType type, int version) {
  2030. return type.Version == version;
  2031. }
  2032. #region Conversion helpers
  2033. internal static MethodInfo GetConversionHelper(string name, ConversionResultKind resultKind) {
  2034. MethodInfo res;
  2035. switch (resultKind) {
  2036. case ConversionResultKind.ExplicitCast:
  2037. case ConversionResultKind.ImplicitCast:
  2038. res = typeof(PythonOps).GetMethod("Throwing" + name);
  2039. break;
  2040. case ConversionResultKind.ImplicitTry:
  2041. case ConversionResultKind.ExplicitTry:
  2042. res = typeof(PythonOps).GetMethod("NonThrowing" + name);
  2043. break;
  2044. default: throw new InvalidOperationException();
  2045. }
  2046. Debug.Assert(res != null);
  2047. return res;
  2048. }
  2049. public static IEnumerable OldInstanceConvertToIEnumerableNonThrowing(CodeContext/*!*/ context, OldInstance/*!*/ self) {
  2050. object callable;
  2051. if (self.TryGetBoundCustomMember(context, Symbols.Iterator, out callable)) {
  2052. return CreatePythonEnumerable(self);
  2053. } else if (self.TryGetBoundCustomMember(context, Symbols.GetItem, out callable)) {
  2054. return CreateItemEnumerable(self);
  2055. }
  2056. return null;
  2057. }
  2058. public static IEnumerable/*!*/ OldInstanceConvertToIEnumerableThrowing(CodeContext/*!*/ context, OldInstance/*!*/ self) {
  2059. IEnumerable res = OldInstanceConvertToIEnumerableNonThrowing(context, self);
  2060. if (res == null) {
  2061. throw TypeErrorForTypeMismatch("IEnumerable", self);
  2062. }
  2063. return res;
  2064. }
  2065. public static IEnumerable<T> OldInstanceConvertToIEnumerableOfTNonThrowing<T>(CodeContext/*!*/ context, OldInstance/*!*/ self) {
  2066. object callable;
  2067. if (self.TryGetBoundCustomMember(context, Symbols.Iterator, out callable)) {
  2068. return new IEnumerableOfTWrapper<T>(CreatePythonEnumerable(self));
  2069. } else if (self.TryGetBoundCustomMember(context, Symbols.GetItem, out callable)) {
  2070. return new IEnumerableOfTWrapper<T>(CreateItemEnumerable(self));
  2071. }
  2072. return null;
  2073. }
  2074. public static IEnumerable<T>/*!*/ OldInstanceConvertToIEnumerableOfTThrowing<T>(CodeContext/*!*/ context, OldInstance/*!*/ self) {
  2075. IEnumerable<T> res = OldInstanceConvertToIEnumerableOfTNonThrowing<T>(context, self);
  2076. if (res == null) {
  2077. throw TypeErrorForTypeMismatch("IEnumerable[T]", self);
  2078. }
  2079. return res;
  2080. }
  2081. public static IEnumerator OldInstanceConvertToIEnumeratorNonThrowing(CodeContext/*!*/ context, OldInstance/*!*/ self) {
  2082. object callable;
  2083. if (self.TryGetBoundCustomMember(context, Symbols.Iterator, out callable)) {
  2084. return CreatePythonEnumerator(self);
  2085. } else if (self.TryGetBoundCustomMember(context, Symbols.GetItem, out callable)) {
  2086. return CreateItemEnumerator(self);
  2087. }
  2088. return null;
  2089. }
  2090. public static IEnumerator/*!*/ OldInstanceConvertToIEnumeratorThrowing(CodeContext/*!*/ context, OldInstance/*!*/ self) {
  2091. IEnumerator res = OldInstanceConvertToIEnumeratorNonThrowing(context, self);
  2092. if (res == null) {
  2093. throw TypeErrorForTypeMismatch("IEnumerator", self);
  2094. }
  2095. return res;
  2096. }
  2097. public static bool? OldInstanceConvertToBoolNonThrowing(CodeContext/*!*/ context, OldInstance/*!*/ oi) {
  2098. object value;
  2099. if (oi.TryGetBoundCustomMember(context, Symbols.NonZero, out value)) {
  2100. object res = NonThrowingConvertToNonZero(PythonCalls.Call(context, value));
  2101. if (res is int) {
  2102. return ((int)res) != 0;
  2103. } else if (res is bool) {
  2104. return (bool)res;
  2105. }
  2106. } else if (oi.TryGetBoundCustomMember(context, Symbols.Length, out value)) {
  2107. int res;
  2108. if (Converter.TryConvertToInt32(PythonCalls.Call(context, value), out res)) {
  2109. return res != 0;
  2110. }
  2111. }
  2112. return null;
  2113. }
  2114. public static object OldInstanceConvertToBoolThrowing(CodeContext/*!*/ context, OldInstance/*!*/ oi) {
  2115. object value;
  2116. if (oi.TryGetBoundCustomMember(context, Symbols.NonZero, out value)) {
  2117. return ThrowingConvertToNonZero(PythonCalls.Call(context, value));
  2118. } else if (oi.TryGetBoundCustomMember(context, Symbols.Length, out value)) {
  2119. return PythonContext.GetContext(context).ConvertToInt32(PythonCalls.Call(context, value)) != 0;
  2120. }
  2121. return null;
  2122. }
  2123. public static object OldInstanceConvertNonThrowing(CodeContext/*!*/ context, OldInstance/*!*/ oi, SymbolId conversion) {
  2124. object value;
  2125. if (oi.TryGetBoundCustomMember(context, conversion, out value)) {
  2126. if (conversion == Symbols.ConvertToInt) {
  2127. return NonThrowingConvertToInt(PythonCalls.Call(context, value));
  2128. } else if (conversion == Symbols.ConvertToLong) {
  2129. return NonThrowingConvertToLong(PythonCalls.Call(context, value));
  2130. } else if (conversion == Symbols.ConvertToFloat) {
  2131. return NonThrowingConvertToFloat(PythonCalls.Call(context, value));
  2132. } else if (conversion == Symbols.ConvertToComplex) {
  2133. return NonThrowingConvertToComplex(PythonCalls.Call(context, value));
  2134. } else if (conversion == Symbols.String) {
  2135. return NonThrowingConvertToString(PythonCalls.Call(context, value));
  2136. } else {
  2137. Debug.Assert(false);
  2138. }
  2139. } else if (conversion == Symbols.ConvertToComplex) {
  2140. object res = OldInstanceConvertNonThrowing(context, oi, Symbols.ConvertToFloat);
  2141. if (res == null) {
  2142. return null;
  2143. }
  2144. return Converter.ConvertToComplex64(res);
  2145. }
  2146. return null;
  2147. }
  2148. public static object OldInstanceConvertThrowing(CodeContext/*!*/ context, OldInstance/*!*/ oi, SymbolId conversion) {
  2149. object value;
  2150. if (oi.TryGetBoundCustomMember(context, conversion, out value)) {
  2151. if (conversion == Symbols.ConvertToInt) {
  2152. return ThrowingConvertToInt(PythonCalls.Call(context, value));
  2153. } else if (conversion == Symbols.ConvertToLong) {
  2154. return ThrowingConvertToLong(PythonCalls.Call(context, value));
  2155. } else if (conversion == Symbols.ConvertToFloat) {
  2156. return ThrowingConvertToFloat(PythonCalls.Call(context, value));
  2157. } else if (conversion == Symbols.ConvertToComplex) {
  2158. return ThrowingConvertToComplex(PythonCalls.Call(context, value));
  2159. } else if (conversion == Symbols.String) {
  2160. return ThrowingConvertToString(PythonCalls.Call(context, value));
  2161. } else {
  2162. Debug.Assert(false);
  2163. }
  2164. } else if (conversion == Symbols.ConvertToComplex) {
  2165. return OldInstanceConvertThrowing(context, oi, Symbols.ConvertToFloat);
  2166. }
  2167. return null;
  2168. }
  2169. internal static bool CheckingConvertToInt(object value) {
  2170. return value is int || value is BigInteger || value is Extensible<int> || value is Extensible<BigInteger>;
  2171. }
  2172. internal static bool CheckingConvertToLong(object value) {
  2173. return CheckingConvertToInt(value);
  2174. }
  2175. internal static bool CheckingConvertToFloat(object value) {
  2176. return value is double || (value != null && value is Extensible<double>);
  2177. }
  2178. internal static bool CheckingConvertToComplex(object value) {
  2179. return value is Complex64 || value is Extensible<Complex64> || CheckingConvertToInt(value) || CheckingConvertToFloat(value);
  2180. }
  2181. internal static bool CheckingConvertToString(object value) {
  2182. return value is string || value is Extensible<string>;
  2183. }
  2184. public static bool CheckingConvertToNonZero(object value) {
  2185. return value is bool || value is int;
  2186. }
  2187. public static object NonThrowingConvertToInt(object value) {
  2188. if (!CheckingConvertToInt(value)) return null;
  2189. return value;
  2190. }
  2191. public static object NonThrowingConvertToLong(object value) {
  2192. if (!CheckingConvertToInt(value)) return null;
  2193. return value;
  2194. }
  2195. public static object NonThrowingConvertToFloat(object value) {
  2196. if (!CheckingConvertToFloat(value)) return null;
  2197. return value;
  2198. }
  2199. public static object NonThrowingConvertToComplex(object value) {
  2200. if (!CheckingConvertToComplex(value)) return null;
  2201. return value;
  2202. }
  2203. public static object NonThrowingConvertToString(object value) {
  2204. if (!CheckingConvertToString(value)) return null;
  2205. return value;
  2206. }
  2207. public static object NonThrowingConvertToNonZero(object value) {
  2208. if (!CheckingConvertToNonZero(value)) return null;
  2209. return value;
  2210. }
  2211. public static object ThrowingConvertToInt(object value) {
  2212. if (!CheckingConvertToInt(value)) throw TypeError(" __int__ returned non-int (type {0})", PythonTypeOps.GetName(value));
  2213. return value;
  2214. }
  2215. public static object ThrowingConvertToFloat(object value) {
  2216. if (!CheckingConvertToFloat(value)) throw TypeError(" __float__ returned non-float (type {0})", PythonTypeOps.GetName(value));
  2217. return value;
  2218. }
  2219. public static object ThrowingConvertToComplex(object value) {
  2220. if (!CheckingConvertToComplex(value)) throw TypeError(" __complex__ returned non-complex (type {0})", PythonTypeOps.GetName(value));
  2221. return value;
  2222. }
  2223. public static object ThrowingConvertToLong(object value) {
  2224. if (!CheckingConvertToComplex(value)) throw TypeError(" __long__ returned non-long (type {0})", PythonTypeOps.GetName(value));
  2225. return value;
  2226. }
  2227. public static object ThrowingConvertToString(object value) {
  2228. if (!CheckingConvertToString(value)) throw TypeError(" __str__ returned non-str (type {0})", PythonTypeOps.GetName(value));
  2229. return value;
  2230. }
  2231. public static bool ThrowingConvertToNonZero(object value) {
  2232. if (!CheckingConvertToNonZero(value)) throw TypeError("__nonzero__ should return bool or int, returned {0}", PythonTypeOps.GetName(value));
  2233. if (value is bool) {
  2234. return (bool)value;
  2235. }
  2236. return ((int)value) != 0;
  2237. }
  2238. #endregion
  2239. public static bool SlotTryGetBoundValue(CodeContext/*!*/ context, PythonTypeSlot/*!*/ slot, object instance, PythonType owner, out object value) {
  2240. return slot.TryGetBoundValue(context, instance, owner, out value);
  2241. }
  2242. public static bool SlotTryGetValue(CodeContext/*!*/ context, PythonTypeSlot/*!*/ slot, object instance, PythonType owner, out object value) {
  2243. return slot.TryGetValue(context, instance, owner, out value);
  2244. }
  2245. public static object SlotGetValue(CodeContext/*!*/ context, PythonTypeSlot/*!*/ slot, object instance, PythonType owner) {
  2246. object value;
  2247. if (!slot.TryGetValue(context, instance, owner, out value)) {
  2248. throw new InvalidOperationException();
  2249. }
  2250. return value;
  2251. }
  2252. public static bool SlotTrySetValue(CodeContext/*!*/ context, PythonTypeSlot/*!*/ slot, object instance, PythonType owner, object value) {
  2253. return slot.TrySetValue(context, instance, owner, value);
  2254. }
  2255. public static object SlotSetValue(CodeContext/*!*/ context, PythonTypeSlot/*!*/ slot, object instance, PythonType owner, object value) {
  2256. if (!slot.TrySetValue(context, instance, owner, value)) {
  2257. throw new InvalidOperationException();
  2258. }
  2259. return value;
  2260. }
  2261. public static bool SlotTryDeleteValue(CodeContext/*!*/ context, PythonTypeSlot/*!*/ slot, object instance, PythonType owner) {
  2262. return slot.TryDeleteValue(context, instance, owner);
  2263. }
  2264. public static BuiltinFunction/*!*/ MakeBoundBuiltinFunction(BuiltinFunction/*!*/ function, object/*!*/ target) {
  2265. return function.BindToInstance(target);
  2266. }
  2267. /// <summary>
  2268. /// Called from generated code. Gets a builtin function and the BuiltinFunctionData associated
  2269. /// with the object. Tests to see if the function is bound and has the same data for the generated
  2270. /// rule.
  2271. /// </summary>
  2272. public static bool TestBoundBuiltinFunction(BuiltinFunction/*!*/ function, object data) {
  2273. if (function.IsUnbound) {
  2274. // not bound
  2275. return false;
  2276. }
  2277. return function.TestData(data);
  2278. }
  2279. public static BuiltinFunction/*!*/ GetBuiltinMethodDescriptorTemplate(BuiltinMethodDescriptor/*!*/ descriptor) {
  2280. return descriptor.Template;
  2281. }
  2282. public static int GetTypeVersion(PythonType type) {
  2283. return type.Version;
  2284. }
  2285. public static bool TryResolveTypeSlot(CodeContext/*!*/ context, PythonType type, SymbolId name, out PythonTypeSlot slot) {
  2286. return type.TryResolveSlot(context, name, out slot);
  2287. }
  2288. public static T[] ConvertTupleToArray<T>(PythonTuple tuple) {
  2289. T[] res = new T[tuple.__len__()];
  2290. for (int i = 0; i < tuple.__len__(); i++) {
  2291. try {
  2292. res[i] = (T)tuple[i];
  2293. } catch (InvalidCastException) {
  2294. res[i] = Converter.Convert<T>(tuple[i]);
  2295. }
  2296. }
  2297. return res;
  2298. }
  2299. #region Function helpers
  2300. [NoSideEffects]
  2301. public static PythonFunction MakeFunction(CodeContext/*!*/ context, string name, Delegate target, string[] argNames, object[] defaults,
  2302. FunctionAttributes attributes, string docString, int lineNumber, string fileName) {
  2303. PythonFunction ret = new PythonFunction(context, name, target, argNames, defaults, attributes);
  2304. if (docString != null) ret.__doc__ = docString;
  2305. ret.func_code.SetLineNumber(lineNumber);
  2306. object fn;
  2307. if (fileName != null) {
  2308. ret.func_code.SetFilename(fileName);
  2309. } else if (context.GlobalScope.Dict.TryGetValue(Symbols.File, out fn) && fn is string) {
  2310. ret.func_code.SetFilename((string)fn);
  2311. }
  2312. ret.func_code.SetFlags(attributes);
  2313. return ret;
  2314. }
  2315. public static CodeContext FunctionGetContext(PythonFunction func) {
  2316. return func.Context;
  2317. }
  2318. public static object FunctionGetDefaultValue(PythonFunction func, int index) {
  2319. return func.Defaults[index];
  2320. }
  2321. public static int FunctionGetCompatibility(PythonFunction func) {
  2322. return func.FunctionCompatibility;
  2323. }
  2324. public static int FunctionGetID(PythonFunction func) {
  2325. return func.FunctionID;
  2326. }
  2327. public static Delegate FunctionGetTarget(PythonFunction func) {
  2328. return func.Target;
  2329. }
  2330. public static void FunctionPushFrame() {
  2331. //HACK ALERT:
  2332. // In interpreted mode, cap the recursion limit at 200, since our stack grows 30x faster than normal.
  2333. //TODO: remove this when we switch to a non-recursive interpretation strategy
  2334. if (PythonContext.GetPythonOptions(null).InterpretedMode) {
  2335. if (PythonFunction.Depth > 200) throw PythonOps.RuntimeError("maximum recursion depth exceeded");
  2336. }
  2337. if (++PythonFunction.Depth > PythonFunction._MaximumDepth)
  2338. throw PythonOps.RuntimeError("maximum recursion depth exceeded");
  2339. }
  2340. public static void FunctionPopFrame() {
  2341. --PythonFunction.Depth;
  2342. }
  2343. public static bool ShouldEnforceRecursion() {
  2344. return PythonFunction.EnforceRecursion;
  2345. }
  2346. #endregion
  2347. public static object ReturnConversionResult(object value) {
  2348. PythonTuple pt = value as PythonTuple;
  2349. if (pt != null) {
  2350. return pt[0];
  2351. }
  2352. return NotImplementedType.Value;
  2353. }
  2354. public static MetaAction MakeListCallAction(int count) {
  2355. ArgumentInfo[] infos = CompilerHelpers.MakeRepeatedArray(ArgumentInfo.Simple, count);
  2356. infos[count - 1] = new ArgumentInfo(ArgumentKind.List);
  2357. return new InvokeBinder(
  2358. DefaultContext.DefaultPythonContext.DefaultBinderState,
  2359. new CallSignature(infos)
  2360. );
  2361. }
  2362. public static MetaAction MakeSimpleCallAction(int count) {
  2363. return new InvokeBinder(
  2364. DefaultContext.DefaultPythonContext.DefaultBinderState,
  2365. new CallSignature(CompilerHelpers.MakeRepeatedArray(ArgumentInfo.Simple, count))
  2366. );
  2367. }
  2368. public static PythonTuple ValidateCoerceResult(object coerceResult) {
  2369. if (coerceResult == null || coerceResult == NotImplementedType.Value) {
  2370. return null;
  2371. }
  2372. PythonTuple pt = coerceResult as PythonTuple;
  2373. if (pt == null) throw PythonOps.TypeError("coercion should return None, NotImplemented, or 2-tuple, got {0}", PythonTypeOps.GetName(coerceResult));
  2374. return pt;
  2375. }
  2376. public static object GetCoerceResultOne(PythonTuple coerceResult) {
  2377. return coerceResult._data[0];
  2378. }
  2379. public static object GetCoerceResultTwo(PythonTuple coerceResult) {
  2380. return coerceResult._data[1];
  2381. }
  2382. public static object MethodCheckSelf(Method method, object self) {
  2383. return method.CheckSelf(self);
  2384. }
  2385. public static object GeneratorCheckThrowableAndReturnSendValue(object self) {
  2386. return ((PythonGenerator)self).CheckThrowableAndReturnSendValue();
  2387. }
  2388. public static ItemEnumerable CreateItemEnumerable(object baseObject) {
  2389. return ItemEnumerable.Create(baseObject);
  2390. }
  2391. public static IEnumerable CreatePythonEnumerable(object baseObject) {
  2392. return PythonEnumerable.Create(baseObject);
  2393. }
  2394. public static IEnumerator CreateItemEnumerator(object baseObject) {
  2395. return ItemEnumerator.Create(baseObject);
  2396. }
  2397. public static IEnumerator CreatePythonEnumerator(object baseObject) {
  2398. return PythonEnumerator.Create(baseObject);
  2399. }
  2400. public static bool ContainsFromEnumerable(CodeContext/*!*/ context, IEnumerator ie, object value) {
  2401. while (ie.MoveNext()) {
  2402. if (PythonOps.EqualRetBool(context, ie.Current, value)) {
  2403. return true;
  2404. }
  2405. }
  2406. return false;
  2407. }
  2408. public static object PythonTypeGetMember(CodeContext/*!*/ context, PythonType type, object instance, SymbolId name) {
  2409. return type.GetMember(context, instance, name);
  2410. }
  2411. [NoSideEffects]
  2412. public static object CheckUninitialized(object value, SymbolId name) {
  2413. if (value == Uninitialized.Instance) {
  2414. RuntimeHelpers.ThrowUnboundLocalError(name);
  2415. }
  2416. return value;
  2417. }
  2418. #region OldClass/OldInstance public helpers
  2419. public static bool OldInstanceIsCallable(CodeContext/*!*/ context, OldInstance/*!*/ self) {
  2420. object dummy;
  2421. return self.TryGetBoundCustomMember(context, Symbols.Call, out dummy);
  2422. }
  2423. public static object OldClassCheckCallError(OldClass/*!*/ self, object dictionary, object list) {
  2424. if ((dictionary != null && PythonOps.Length(dictionary) != 0) ||
  2425. (list != null && PythonOps.Length(list) != 0)) {
  2426. return self.MakeCallError();
  2427. }
  2428. return null;
  2429. }
  2430. public static void OldClassSetBases(OldClass oc, object value) {
  2431. oc.SetBases(value);
  2432. }
  2433. public static void OldClassSetName(OldClass oc, object value) {
  2434. oc.SetName(value);
  2435. }
  2436. public static void OldClassSetDictionary(OldClass oc, object value) {
  2437. oc.SetDictionary(value);
  2438. }
  2439. public static void OldClassSetNameHelper(OldClass oc, SymbolId name, object value) {
  2440. oc.SetNameHelper(name, value);
  2441. }
  2442. public static bool OldClassTryLookupInit(OldClass oc, object inst, out object ret) {
  2443. return oc.TryLookupInit(inst, out ret);
  2444. }
  2445. public static object OldClassMakeCallError(OldClass oc) {
  2446. return oc.MakeCallError();
  2447. }
  2448. public static PythonTuple OldClassGetBaseClasses(OldClass oc) {
  2449. return PythonTuple.MakeTuple(oc.BaseClasses.ToArray());
  2450. }
  2451. public static void OldClassDictionaryIsPublic(OldClass oc) {
  2452. oc.DictionaryIsPublic();
  2453. }
  2454. public static bool OldClassTryLookupValue(CodeContext context, OldClass oc, SymbolId name, out object value) {
  2455. return oc.TryLookupValue(context, name, out value);
  2456. }
  2457. public static object OldClassLookupValue(CodeContext context, OldClass oc, SymbolId name) {
  2458. return oc.LookupValue(context, name);
  2459. }
  2460. public static object OldInstanceGetOptimizedDictionary(OldInstance instance, int keyVersion) {
  2461. CustomOldClassDictionaryStorage storage = instance.Dictionary._storage as CustomOldClassDictionaryStorage;
  2462. if (storage == null || instance._class.HasSetAttr || storage.KeyVersion != keyVersion) {
  2463. return null;
  2464. }
  2465. return storage;
  2466. }
  2467. public static object OldInstanceDictionaryGetValueHelper(object dict, int index, object oldInstance) {
  2468. return ((CustomOldClassDictionaryStorage)dict).GetValueHelper(index, oldInstance);
  2469. }
  2470. public static object OldInstanceGetBoundMember(CodeContext context, OldInstance instance, SymbolId name) {
  2471. return instance.GetBoundMember(context, name);
  2472. }
  2473. public static void OldInstanceDictionarySetExtraValue(object dict, int index, object value) {
  2474. ((CustomOldClassDictionaryStorage)dict).SetExtraValue(index, value);
  2475. }
  2476. public static bool OldClassDeleteMember(CodeContext context, OldClass self, SymbolId name) {
  2477. return self.DeleteCustomMember(context, name);
  2478. }
  2479. public static bool OldClassTryLookupOneSlot(OldClass self, SymbolId name, out object value) {
  2480. return self.TryLookupOneSlot(name, out value);
  2481. }
  2482. public static bool OldInstanceTryGetBoundCustomMember(CodeContext context, OldInstance self, SymbolId name, out object value) {
  2483. return self.TryGetBoundCustomMember(context, name, out value);
  2484. }
  2485. public static void OldInstanceSetCustomMember(CodeContext context, OldInstance self, SymbolId name, object value) {
  2486. self.SetCustomMember(context, name, value);
  2487. }
  2488. public static bool OldInstanceDeleteCustomMember(CodeContext context, OldInstance self, SymbolId name) {
  2489. return self.DeleteCustomMember(context, name);
  2490. }
  2491. #endregion
  2492. public static void PythonTypeSetCustomMember(CodeContext context, PythonType self, SymbolId name, object value) {
  2493. self.SetCustomMember(context, name, value);
  2494. }
  2495. public static bool PythonTypeDeleteCustomMember(CodeContext context, PythonType self, SymbolId name) {
  2496. return self.DeleteCustomMember(context, name);
  2497. }
  2498. public static bool IsPythonType(PythonType type) {
  2499. return type.IsPythonType;
  2500. }
  2501. public static object PublishModule(CodeContext/*!*/ context, string name) {
  2502. object original = null;
  2503. PythonContext.GetContext(context).SystemStateModules.TryGetValue(name, out original);
  2504. PythonContext.GetContext(context).SystemStateModules[name] = context.Scope;
  2505. return original;
  2506. }
  2507. public static void RemoveModule(CodeContext/*!*/ context, string name, object oldValue) {
  2508. if (oldValue != null) {
  2509. PythonContext.GetContext(context).SystemStateModules[name] = oldValue;
  2510. } else {
  2511. PythonContext.GetContext(context).SystemStateModules.Remove(name);
  2512. }
  2513. }
  2514. public static Ellipsis Ellipsis {
  2515. get {
  2516. return Ellipsis.Value;
  2517. }
  2518. }
  2519. public static NotImplementedType NotImplemented {
  2520. get {
  2521. return NotImplementedType.Value;
  2522. }
  2523. }
  2524. public static void ListAddForComprehension(List l, object o) {
  2525. l.AddNoLock(o);
  2526. }
  2527. public static PythonGenerator MarkGeneratorWithExceptionHandling(PythonGenerator/*!*/ generator) {
  2528. Debug.Assert(generator != null);
  2529. generator.CanSetSysExcInfo = true;
  2530. return generator;
  2531. }
  2532. public static void InitializePythonGenerator(PythonGenerator/*!*/ generator, IEnumerator/*!*/ enumerator) {
  2533. generator.Next = enumerator;
  2534. }
  2535. public static object GetUserDescriptorValue(object instance, PythonTypeSlot slot) {
  2536. return GetUserDescriptor(((PythonTypeUserDescriptorSlot)slot).Value, instance, ((IPythonObject)instance).PythonType);
  2537. }
  2538. public static void ModuleStarted(CodeContext/*!*/ context, object binderState, PythonLanguageFeatures features) {
  2539. PythonModule scopeExtension = (PythonModule)context.LanguageContext.EnsureScopeExtension(context.Scope.ModuleScope);
  2540. if ((features & PythonLanguageFeatures.AbsoluteImports) != 0) {
  2541. scopeExtension.AbsoluteImports = true;
  2542. }
  2543. if ((features & PythonLanguageFeatures.AllowWithStatement) != 0) {
  2544. scopeExtension.AllowWithStatement = true;
  2545. }
  2546. if ((features & PythonLanguageFeatures.TrueDivision) != 0) {
  2547. scopeExtension.TrueDivision = true;
  2548. }
  2549. BinderState state = binderState as BinderState;
  2550. if (state != null) {
  2551. state.Context = context;
  2552. }
  2553. }
  2554. public static void Warn(CodeContext/*!*/ context, PythonType category, string message, params object[] args) {
  2555. PythonContext pc = PythonContext.GetContext(context);
  2556. object warnings = null, warn = null;
  2557. try {
  2558. if (!pc._importWarningThrows) {
  2559. warnings = Importer.ImportModule(context, new PythonDictionary(), "warnings", false, -1);
  2560. }
  2561. } catch {
  2562. // don't repeatedly import after it fails
  2563. pc._importWarningThrows = true;
  2564. }
  2565. if (warnings != null) {
  2566. warn = PythonOps.GetBoundAttr(context, warnings, SymbolTable.StringToId("warn"));
  2567. }
  2568. for (int i = 0; i < args.Length; i++) {
  2569. args[i] = PythonOps.ToString(args[i]);
  2570. }
  2571. message = String.Format(message, args);
  2572. if (warn == null) {
  2573. PythonOps.PrintWithDest(context, pc.SystemStandardError, "warning: " + category.Name + ": " + message);
  2574. } else {
  2575. PythonOps.CallWithContext(context, warn, message, category);
  2576. }
  2577. }
  2578. private static bool IsPrimitiveNumber(object o) {
  2579. return IsNumericObject(o) ||
  2580. o is Complex64 ||
  2581. o is double ||
  2582. o is Extensible<Complex64> ||
  2583. o is Extensible<double>;
  2584. }
  2585. public static void WarnDivision(CodeContext/*!*/ context, PythonDivisionOptions options, object self, object other) {
  2586. if (options == PythonDivisionOptions.WarnAll) {
  2587. if (IsPrimitiveNumber(self) && IsPrimitiveNumber(other)) {
  2588. if (self is Complex64 || other is Complex64 || self is Extensible<Complex64> || other is Extensible<Complex64>) {
  2589. Warn(context, PythonExceptions.DeprecationWarning, "classic complex division");
  2590. return;
  2591. } else if (self is double || other is double || self is Extensible<double> || other is Extensible<double>) {
  2592. Warn(context, PythonExceptions.DeprecationWarning, "classic float division");
  2593. return;
  2594. } else {
  2595. WarnDivisionInts(context, self, other);
  2596. }
  2597. }
  2598. } else if (IsNumericObject(self) && IsNumericObject(other)) {
  2599. WarnDivisionInts(context, self, other);
  2600. }
  2601. }
  2602. private static void WarnDivisionInts(CodeContext/*!*/ context, object self, object other) {
  2603. if (self is BigInteger || other is BigInteger || self is Extensible<BigInteger> || other is Extensible<BigInteger>) {
  2604. Warn(context, PythonExceptions.DeprecationWarning, "classic long division");
  2605. } else {
  2606. Warn(context, PythonExceptions.DeprecationWarning, "classic int division");
  2607. }
  2608. }
  2609. public static object GetInitialBinderState(CodeContext/*!*/ context) {
  2610. return GetBinderState(context);
  2611. }
  2612. internal static BinderState GetBinderState(CodeContext/*!*/ context) {
  2613. PythonModule pm = PythonContext.GetContext(context).GetPythonModule(context.GlobalScope);
  2614. Debug.Assert(pm.BinderState != null);
  2615. return pm.BinderState;
  2616. }
  2617. public static MetaAction MakeInvokeAction(CodeContext/*!*/ context, CallSignature signature) {
  2618. return new InvokeBinder(GetBinderState(context), signature);
  2619. }
  2620. public static MetaAction MakeGetAction(CodeContext/*!*/ context, string name, bool isNoThrow) {
  2621. return new GetMemberBinder(GetBinderState(context), name, isNoThrow);
  2622. }
  2623. public static MetaAction MakeSetAction(CodeContext/*!*/ context, string name) {
  2624. return new SetMemberBinder(GetBinderState(context), name);
  2625. }
  2626. public static MetaAction MakeDeleteAction(CodeContext/*!*/ context, string name) {
  2627. return new DeleteMemberBinder(GetBinderState(context), name);
  2628. }
  2629. public static MetaAction MakeConversionAction(CodeContext/*!*/ context, Type type, ConversionResultKind kind) {
  2630. return new ConversionBinder(GetBinderState(context), type, kind);
  2631. }
  2632. public static MetaAction MakeOperationAction(CodeContext/*!*/ context, string operationName) {
  2633. return new OperationBinder(GetBinderState(context), operationName);
  2634. }
  2635. /// <summary>
  2636. /// Provides access to AppDomain.DefineDynamicAssembly which cannot be called from a DynamicMethod
  2637. /// </summary>
  2638. public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) {
  2639. return AppDomain.CurrentDomain.DefineDynamicAssembly(name, access);
  2640. }
  2641. /// <summary>
  2642. /// Provides the entry point for a compiled module. The stub exe calls into InitializeModule which
  2643. /// does the actual work of adding references and importing the main module. Upon completion it returns
  2644. /// the exit code that the program reported via SystemExit or 0.
  2645. /// </summary>
  2646. public static int InitializeModule(Assembly/*!*/ precompiled, string/*!*/ main, string[] references) {
  2647. ContractUtils.RequiresNotNull(precompiled, "precompiled");
  2648. ContractUtils.RequiresNotNull(main, "main");
  2649. var pythonEngine = Python.CreateEngine();
  2650. pythonEngine.Runtime.LoadAssembly(typeof(string).Assembly);
  2651. pythonEngine.Runtime.LoadAssembly(typeof(System.Diagnostics.Debug).Assembly);
  2652. var pythonContext = (PythonContext)HostingHelpers.GetLanguageContext(pythonEngine);
  2653. foreach (var scriptCode in ScriptCode.LoadFromAssembly(pythonContext.DomainManager, precompiled)) {
  2654. pythonContext.GetCompiledLoader().AddScriptCode(scriptCode);
  2655. }
  2656. if (references != null) {
  2657. foreach (string referenceName in references) {
  2658. pythonContext.DomainManager.LoadAssembly(Assembly.Load(referenceName));
  2659. }
  2660. }
  2661. // import __main__
  2662. try {
  2663. Importer.Import(new CodeContext(new Scope(), pythonContext), main, PythonTuple.EMPTY, 0);
  2664. } catch (SystemExitException ex) {
  2665. object dummy;
  2666. return ex.GetExitCode(out dummy);
  2667. }
  2668. return 0;
  2669. }
  2670. public static CodeContext GetPythonTypeContext(PythonType pt) {
  2671. return pt.PythonContext.DefaultBinderState.Context;
  2672. }
  2673. public static int CompareLists(List self, List other) {
  2674. return self.CompareTo(other);
  2675. }
  2676. public static int CompareTuples(PythonTuple self, PythonTuple other) {
  2677. return self.CompareTo(other);
  2678. }
  2679. public static int CompareFloats(double self, double other) {
  2680. return DoubleOps.Compare(self, other);
  2681. }
  2682. #region Exception Factories
  2683. private static Exception MultipleKeywordArgumentError(PythonFunction function, string name) {
  2684. return TypeError("{0}() got multiple values for keyword argument '{1}'", function.__name__, name);
  2685. }
  2686. public static Exception UnexpectedKeywordArgumentError(PythonFunction function, string name) {
  2687. return TypeError("{0}() got an unexpected keyword argument '{1}'", function.__name__, name);
  2688. }
  2689. public static Exception StaticAssignmentFromInstanceError(PropertyTracker tracker, bool isAssignment) {
  2690. return new MissingMemberException(string.Format(isAssignment ? Resources.StaticAssignmentFromInstanceError : Resources.StaticAccessFromInstanceError, tracker.Name, tracker.DeclaringType.Name));
  2691. }
  2692. public static Exception FunctionBadArgumentError(PythonFunction func, int count) {
  2693. return func.BadArgumentError(count);
  2694. }
  2695. public static Exception BadKeywordArgumentError(PythonFunction func, int count) {
  2696. return func.BadKeywordArgumentError(count);
  2697. }
  2698. public static Exception AttributeErrorForMissingOrReadonly(CodeContext/*!*/ context, PythonType dt, SymbolId name) {
  2699. PythonTypeSlot dts;
  2700. if (dt.TryResolveSlot(context, name, out dts)) {
  2701. throw PythonOps.AttributeErrorForReadonlyAttribute(dt.Name, name);
  2702. }
  2703. throw PythonOps.AttributeErrorForMissingAttribute(dt.Name, name);
  2704. }
  2705. public static Exception AttributeErrorForMissingAttribute(object o, SymbolId name) {
  2706. PythonType dt = o as PythonType;
  2707. if (dt != null)
  2708. return PythonOps.AttributeErrorForMissingAttribute(dt.Name, name);
  2709. return AttributeErrorForReadonlyAttribute(PythonTypeOps.GetName(o), name);
  2710. }
  2711. public static Exception ValueError(string format, params object[] args) {
  2712. return new ArgumentException(string.Format(format, args));
  2713. }
  2714. public static Exception KeyError(object key) {
  2715. return PythonExceptions.CreateThrowable(PythonExceptions.KeyError, key);
  2716. }
  2717. public static Exception KeyError(string format, params object[] args) {
  2718. return new KeyNotFoundException(string.Format(format, args));
  2719. }
  2720. public static Exception UnicodeEncodeError(string format, params object[] args) {
  2721. #if SILVERLIGHT // EncoderFallbackException and DecoderFallbackException
  2722. throw new NotImplementedException();
  2723. #else
  2724. return new System.Text.DecoderFallbackException(string.Format(format, args));
  2725. #endif
  2726. }
  2727. public static Exception UnicodeDecodeError(string format, params object[] args) {
  2728. #if SILVERLIGHT // EncoderFallbackException and DecoderFallbackException
  2729. throw new NotImplementedException();
  2730. #else
  2731. return new System.Text.EncoderFallbackException(string.Format(format, args));
  2732. #endif
  2733. }
  2734. public static Exception IOError(Exception inner) {
  2735. return new System.IO.IOException(inner.Message, inner);
  2736. }
  2737. public static Exception IOError(string format, params object[] args) {
  2738. return new System.IO.IOException(string.Format(format, args));
  2739. }
  2740. public static Exception EofError(string format, params object[] args) {
  2741. return new System.IO.EndOfStreamException(string.Format(format, args));
  2742. }
  2743. public static Exception StandardError(string format, params object[] args) {
  2744. return new SystemException(string.Format(format, args));
  2745. }
  2746. public static Exception ZeroDivisionError(string format, params object[] args) {
  2747. return new DivideByZeroException(string.Format(format, args));
  2748. }
  2749. public static Exception SystemError(string format, params object[] args) {
  2750. return new SystemException(string.Format(format, args));
  2751. }
  2752. public static Exception TypeError(string format, params object[] args) {
  2753. return new ArgumentTypeException(string.Format(format, args));
  2754. }
  2755. public static Exception IndexError(string format, params object[] args) {
  2756. return new System.IndexOutOfRangeException(string.Format(format, args));
  2757. }
  2758. public static Exception MemoryError(string format, params object[] args) {
  2759. return new OutOfMemoryException(string.Format(format, args));
  2760. }
  2761. public static Exception ArithmeticError(string format, params object[] args) {
  2762. return new ArithmeticException(string.Format(format, args));
  2763. }
  2764. public static Exception NotImplementedError(string format, params object[] args) {
  2765. return new NotImplementedException(string.Format(format, args));
  2766. }
  2767. public static Exception AttributeError(string format, params object[] args) {
  2768. return new MissingMemberException(string.Format(format, args));
  2769. }
  2770. public static Exception OverflowError(string format, params object[] args) {
  2771. return new System.OverflowException(string.Format(format, args));
  2772. }
  2773. public static Exception WindowsError(string format, params object[] args) {
  2774. #if !SILVERLIGHT // System.ComponentModel.Win32Exception
  2775. return new System.ComponentModel.Win32Exception(string.Format(format, args));
  2776. #else
  2777. return new System.SystemException(string.Format(format, args));
  2778. #endif
  2779. }
  2780. public static Exception SystemExit() {
  2781. return new SystemExitException();
  2782. }
  2783. public static Exception SyntaxWarning(string message, SourceUnit sourceUnit, SourceSpan span, int errorCode) {
  2784. int line = span.Start.Line;
  2785. string fileName = sourceUnit.Path ?? "?";
  2786. if (sourceUnit != null) {
  2787. message = String.Format("{0} ({1}, line {2})", message, fileName, line);
  2788. }
  2789. return SyntaxWarning(message, fileName, span.Start.Line, span.Start.Column, sourceUnit.GetCodeLine(line), Severity.FatalError);
  2790. }
  2791. public static SyntaxErrorException SyntaxError(string message, SourceUnit sourceUnit, SourceSpan span, int errorCode) {
  2792. switch (errorCode & ErrorCodes.ErrorMask) {
  2793. case ErrorCodes.IndentationError:
  2794. return new IndentationException(message, sourceUnit, span, errorCode, Severity.FatalError);
  2795. case ErrorCodes.TabError:
  2796. return new TabException(message, sourceUnit, span, errorCode, Severity.FatalError);
  2797. default:
  2798. return new SyntaxErrorException(message, sourceUnit, span, errorCode, Severity.FatalError);
  2799. }
  2800. }
  2801. public static Exception StopIteration() {
  2802. return StopIteration("");
  2803. }
  2804. public static Exception InvalidType(object o, RuntimeTypeHandle handle) {
  2805. return PythonOps.TypeErrorForTypeMismatch(DynamicHelpers.GetPythonTypeFromType(Type.GetTypeFromHandle(handle)).Name, o);
  2806. }
  2807. public static Exception ZeroDivisionError() {
  2808. return ZeroDivisionError("Attempted to divide by zero.");
  2809. }
  2810. // If you do "(a, b) = (1, 2, 3, 4)"
  2811. public static Exception ValueErrorForUnpackMismatch(int left, int right) {
  2812. System.Diagnostics.Debug.Assert(left != right);
  2813. if (left > right)
  2814. return ValueError("need more than {0} values to unpack", right);
  2815. else
  2816. return ValueError("too many values to unpack");
  2817. }
  2818. public static Exception NameError(SymbolId name) {
  2819. return new UnboundNameException(string.Format("name '{0}' is not defined", SymbolTable.IdToString(name)));
  2820. }
  2821. // If an unbound method is called without a "self" argument, or a "self" argument of a bad type
  2822. public static Exception TypeErrorForUnboundMethodCall(string methodName, Type methodType, object instance) {
  2823. return TypeErrorForUnboundMethodCall(methodName, DynamicHelpers.GetPythonTypeFromType(methodType), instance);
  2824. }
  2825. public static Exception TypeErrorForUnboundMethodCall(string methodName, PythonType methodType, object instance) {
  2826. string message = string.Format("unbound method {0}() must be called with {1} instance as first argument (got {2} instead)",
  2827. methodName, methodType.Name, DynamicHelpers.GetPythonType(instance).Name);
  2828. return TypeError(message);
  2829. }
  2830. // When a generator first starts, before it gets to the first yield point, you can't call generator.Send(x) where x != null.
  2831. // See Pep342 for details.
  2832. public static Exception TypeErrorForIllegalSend() {
  2833. string message = "can't send non-None value to a just-started generator";
  2834. return TypeError(message);
  2835. }
  2836. // If a method is called with an incorrect number of arguments
  2837. // You should use TypeErrorForUnboundMethodCall() for unbound methods called with 0 arguments
  2838. public static Exception TypeErrorForArgumentCountMismatch(string methodName, int expectedArgCount, int actualArgCount) {
  2839. return TypeError("{0}() takes exactly {1} argument{2} ({3} given)",
  2840. methodName, expectedArgCount, expectedArgCount == 1 ? "" : "s", actualArgCount);
  2841. }
  2842. public static Exception TypeErrorForTypeMismatch(string expectedTypeName, object instance) {
  2843. return TypeError("expected {0}, got {1}", expectedTypeName, PythonOps.GetPythonTypeName(instance));
  2844. }
  2845. // If hash is called on an instance of an unhashable type
  2846. public static Exception TypeErrorForUnhashableType(string typeName) {
  2847. return TypeError(typeName + " objects are unhashable");
  2848. }
  2849. internal static Exception TypeErrorForIncompatibleObjectLayout(string prefix, PythonType type, Type newType) {
  2850. return TypeError("{0}: '{1}' object layout differs from '{2}'", prefix, type.Name, newType);
  2851. }
  2852. public static Exception TypeErrorForNonStringAttribute() {
  2853. return TypeError("attribute name must be string");
  2854. }
  2855. internal static Exception TypeErrorForBadInstance(string template, object instance) {
  2856. return TypeError(template, PythonOps.GetPythonTypeName(instance));
  2857. }
  2858. public static Exception TypeErrorForBinaryOp(string opSymbol, object x, object y) {
  2859. throw PythonOps.TypeError("unsupported operand type(s) for {0}: '{1}' and '{2}'",
  2860. opSymbol, GetPythonTypeName(x), GetPythonTypeName(y));
  2861. }
  2862. public static Exception TypeErrorForUnaryOp(string opSymbol, object x) {
  2863. throw PythonOps.TypeError("unsupported operand type for {0}: '{1}'",
  2864. opSymbol, GetPythonTypeName(x));
  2865. }
  2866. public static Exception TypeErrorForNonIterableObject(object o) {
  2867. return PythonOps.TypeError(
  2868. "argument of type '{0}' is not iterable",
  2869. DynamicHelpers.GetPythonType(o).Name
  2870. );
  2871. }
  2872. public static Exception TypeErrorForDefaultArgument(string message) {
  2873. return PythonOps.TypeError(message);
  2874. }
  2875. public static Exception AttributeErrorForReadonlyAttribute(string typeName, SymbolId attributeName) {
  2876. // CPython uses AttributeError for all attributes except "__class__"
  2877. if (attributeName == Symbols.Class)
  2878. return PythonOps.TypeError("can't delete __class__ attribute");
  2879. return PythonOps.AttributeError("attribute '{0}' of '{1}' object is read-only", SymbolTable.IdToString(attributeName), typeName);
  2880. }
  2881. public static Exception AttributeErrorForBuiltinAttributeDeletion(string typeName, SymbolId attributeName) {
  2882. return PythonOps.AttributeError("cannot delete attribute '{0}' of builtin type '{1}'", SymbolTable.IdToString(attributeName), typeName);
  2883. }
  2884. public static Exception MissingInvokeMethodException(object o, string name) {
  2885. if (o is OldClass) {
  2886. throw PythonOps.AttributeError("type object '{0}' has no attribute '{1}'",
  2887. ((OldClass)o).__name__, name);
  2888. } else {
  2889. throw PythonOps.AttributeError("'{0}' object has no attribute '{1}'", GetPythonTypeName(o), name);
  2890. }
  2891. }
  2892. /// <summary>
  2893. /// Create at TypeError exception for when Raise() can't create the exception requested.
  2894. /// </summary>
  2895. /// <param name="type">original type of exception requested</param>
  2896. /// <returns>a TypeEror exception</returns>
  2897. internal static Exception MakeExceptionTypeError(object type) {
  2898. return PythonOps.TypeError("exceptions must be classes, instances, or strings (deprecated), not {0}", DynamicHelpers.GetPythonType(type));
  2899. }
  2900. public static Exception AttributeErrorForMissingAttribute(string typeName, SymbolId attributeName) {
  2901. return PythonOps.AttributeError("'{0}' object has no attribute '{1}'", typeName, SymbolTable.IdToString(attributeName));
  2902. }
  2903. public static Exception UncallableError(object func) {
  2904. return PythonOps.TypeError("{0} is not callable", PythonTypeOps.GetName(func));
  2905. }
  2906. public static Exception TypeErrorForProtectedMember(Type/*!*/ type, string/*!*/ name) {
  2907. return PythonOps.TypeError("cannot access protected member {0} without a python subclass of {1}", name, NameConverter.GetTypeName(type));
  2908. }
  2909. public static Exception TypeErrorForGenericMethod(Type/*!*/ type, string/*!*/ name) {
  2910. return PythonOps.TypeError("{0}.{1} is a generic method and must be indexed with types before calling", NameConverter.GetTypeName(type), name);
  2911. }
  2912. public static Exception TypeErrorForUnIndexableObject(object o) {
  2913. IPythonObject ipo;
  2914. if (o == null) {
  2915. return PythonOps.TypeError("'NoneType' object cannot be interpreted as an index");
  2916. } else if ((ipo = o as IPythonObject) != null) {
  2917. return TypeError("'{0}' object cannot be interpreted as an index", ipo.PythonType.Name);
  2918. }
  2919. return TypeError("object cannot be interpreted as an index");
  2920. }
  2921. public static Exception/*!*/ TypeErrorForBadDictionaryArgument(PythonFunction/*!*/ f) {
  2922. return PythonOps.TypeError("{0}() argument after ** must be a dictionary", f.__name__);
  2923. }
  2924. public static T TypeErrorForBadEnumConversion<T>(object value) {
  2925. throw TypeError("Cannot convert numeric value {0} to {1}. The value must be zero.", value, NameConverter.GetTypeName(typeof(T)));
  2926. }
  2927. public static Exception/*!*/ UnreadableProperty() {
  2928. return PythonOps.AttributeError("unreadable attribute");
  2929. }
  2930. public static Exception/*!*/ UnsetableProperty() {
  2931. return PythonOps.AttributeError("readonly attribute");
  2932. }
  2933. public static Exception/*!*/ UndeletableProperty() {
  2934. return PythonOps.AttributeError("undeletable attribute");
  2935. }
  2936. #endregion
  2937. }
  2938. }