/IronPython_2_0/Src/IronPython/Runtime/Operations/PythonOps.cs
C# | 3577 lines | 2563 code | 639 blank | 375 comment | 808 complexity | 98fd65ba22ddfc25097337ab2079c07c MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Microsoft Public License. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Microsoft Public License, please send an email to
- * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Microsoft Public License.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
-
- using System; using Microsoft;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Reflection;
- using System.Reflection.Emit;
- using Microsoft.Scripting;
- using Microsoft.Scripting.Actions;
- using System.Text;
- using System.Threading;
-
- using Microsoft.Scripting.Generation;
- using Microsoft.Scripting.Hosting;
- using Microsoft.Scripting.Hosting.Shell;
- using Microsoft.Scripting.Math;
- using Microsoft.Scripting.Runtime;
- using Microsoft.Scripting.Utils;
- using Microsoft.Scripting.Hosting.Providers;
-
- using IronPython.Compiler;
- using IronPython.Hosting;
- using IronPython.Runtime.Binding;
- using IronPython.Runtime.Exceptions;
- using IronPython.Runtime.Types;
-
- namespace IronPython.Runtime.Operations {
-
- /// <summary>
- /// Contains functions that are called directly from
- /// generated code to perform low-level runtime functionality.
- /// </summary>
- public static partial class PythonOps {
- #region Shared static data
-
- [ThreadStatic]
- private static List<object> InfiniteRepr;
-
- // The "current" exception on this thread that will be returned via sys.exc_info()
- [ThreadStatic]
- internal static Exception RawException;
-
- #endregion
-
- public static BigInteger MakeIntegerFromHex(string s) {
- return LiteralParser.ParseBigInteger(s, 16);
- }
-
- public static PythonDictionary MakeDict(int size) {
- return new PythonDictionary(size);
- }
-
- /// <summary>
- /// Creates a new dictionary extracting the keys & valeus from the
- /// provided data array. Keys/values are adjacent in the array with
- /// the value coming first.
- /// </summary>
- public static PythonDictionary MakeDictFromItems(object[] data) {
- return new PythonDictionary(new CommonDictionaryStorage(data, false));
- }
-
- /// <summary>
- /// Creates a new dictionary extracting the keys & valeus from the
- /// provided data array. Keys/values are adjacent in the array with
- /// the value coming first.
- /// </summary>
- public static PythonDictionary MakeHomogeneousDictFromItems(object[] data) {
- return new PythonDictionary(new CommonDictionaryStorage(data, true));
- }
-
- public static bool IsCallable(CodeContext/*!*/ context, object o) {
- // This tells if an object can be called, but does not make a claim about the parameter list.
- // In 1.x, we could check for certain interfaces like ICallable*, but those interfaces were deprecated
- // in favor of dynamic sites.
- // This is difficult to infer because we'd need to simulate the entire callbinder, which can include
- // looking for [SpecialName] call methods and checking for a rule from IDynamicObject. But even that wouldn't
- // be complete since sites require the argument list of the call, and we only have the instance here.
- // Thus check a dedicated IsCallable operator. This lets each object describe if it's callable.
-
-
- // Invoke Operator.IsCallable on the object.
- return PythonContext.GetContext(context).IsCallable(o);
- }
-
- public static bool IsTrue(object o) {
- return Converter.ConvertToBoolean(o);
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
- public static List<object> GetReprInfinite() {
- if (InfiniteRepr == null) {
- InfiniteRepr = new List<object>();
- }
- return InfiniteRepr;
- }
-
- #if !SILVERLIGHT
-
- internal static object LookupEncodingError(CodeContext/*!*/ context, string name) {
- Dictionary<string, object> errorHandlers = PythonContext.GetContext(context).ErrorHandlers;
- lock (errorHandlers) {
- if (errorHandlers.ContainsKey(name))
- return errorHandlers[name];
- else
- throw PythonOps.LookupError("unknown error handler name '{0}'", name);
- }
- }
-
- internal static void RegisterEncodingError(CodeContext/*!*/ context, string name, object handler) {
- Dictionary<string, object> errorHandlers = PythonContext.GetContext(context).ErrorHandlers;
-
- lock (errorHandlers) {
- if (!PythonOps.IsCallable(context, handler))
- throw PythonOps.TypeError("handler must be callable");
-
- errorHandlers[name] = handler;
- }
- }
-
- #endif
-
- internal static PythonTuple LookupEncoding(CodeContext/*!*/ context, string encoding) {
- List<object> searchFunctions = PythonContext.GetContext(context).SearchFunctions;
- lock (searchFunctions) {
- for (int i = 0; i < searchFunctions.Count; i++) {
- object res = PythonCalls.Call(context, searchFunctions[i], encoding);
- if (res != null) return (PythonTuple)res;
- }
- }
-
- throw PythonOps.LookupError("unknown encoding: {0}", encoding);
- }
-
- internal static void RegisterEncoding(CodeContext/*!*/ context, object search_function) {
- if(!PythonOps.IsCallable(context, search_function))
- throw PythonOps.TypeError("search_function must be callable");
-
- List<object> searchFunctions = PythonContext.GetContext(context).SearchFunctions;
-
- lock (searchFunctions) {
- searchFunctions.Add(search_function);
- }
- }
-
- internal static string GetPythonTypeName(object obj) {
- OldInstance oi = obj as OldInstance;
- if (oi != null) return oi._class._name.ToString();
- else return DynamicHelpers.GetPythonType(obj).Name;
- }
-
- public static string Repr(CodeContext/*!*/ context, object o) {
- if (o == null) return "None";
-
- string s;
- if ((s = o as string) != null) return StringOps.__repr__(s);
- if (o is int) return Int32Ops.__repr__((int)o);
- if (o is long) return ((long)o).ToString() + "L";
-
- // could be a container object, we need to detect recursion, but only
- // for our own built-in types that we're aware of. The user can setup
- // infinite recursion in their own class if they want.
- ICodeFormattable f = o as ICodeFormattable;
- if (f != null) {
- return f.__repr__(context);
- }
-
- PerfTrack.NoteEvent(PerfTrack.Categories.Temporary, "Repr " + o.GetType().FullName);
-
- return PythonContext.InvokeUnaryOperator(context, UnaryOperators.Repr, o) as string;
- }
-
- public static List<object> GetAndCheckInfinite(object o) {
- List<object> infinite = GetReprInfinite();
- foreach (object o2 in infinite) {
- if (o == o2) {
- return null;
- }
- }
- return infinite;
- }
-
- public static string ToString(object o) {
- return ToString(DefaultContext.Default, o);
- }
-
- public static string ToString(CodeContext/*!*/ context, object o) {
- string x = o as string;
- PythonType dt;
- OldClass oc;
- if (x != null) return x;
- if (o == null) return "None";
- if (o is double) return DoubleOps.__str__(context, (double)o);
- if ((dt = o as PythonType) != null) return dt.__repr__(DefaultContext.Default);
- if ((oc = o as OldClass) != null) return oc.ToString();
-
- object value = PythonContext.InvokeUnaryOperator(context, UnaryOperators.String, o);
- string ret = value as string;
- if (ret == null) {
- Extensible<string> es = value as Extensible<string>;
- if (es == null) {
- throw PythonOps.TypeError("expected str, got {0} from __str__", DynamicHelpers.GetPythonType(value).Name);
- }
-
- ret = es.Value;
- }
- return ret;
- }
-
- public static object Plus(object o) {
- object ret;
-
- if (o is int) return o;
- else if (o is double) return o;
- else if (o is BigInteger) return o;
- else if (o is Complex64) return o;
- else if (o is long) return o;
- else if (o is float) return o;
- else if (o is bool) return RuntimeHelpers.Int32ToObject((bool)o ? 1 : 0);
-
- if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default, o, Symbols.Positive, out ret) &&
- ret != NotImplementedType.Value) {
- return ret;
- }
-
- throw PythonOps.TypeError("bad operand type for unary +");
- }
-
- public static object Negate(object o) {
- if (o is int) return Int32Ops.Negate((int)o);
- else if (o is double) return DoubleOps.Negate((double)o);
- else if (o is long) return Int64Ops.Negate((long)o);
- else if (o is BigInteger) return BigIntegerOps.Negate((BigInteger)o);
- else if (o is Complex64) return -(Complex64)o;
- else if (o is float) return DoubleOps.Negate((float)o);
- else if (o is bool) return RuntimeHelpers.Int32ToObject((bool)o ? -1 : 0);
-
- object ret;
- if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default, o, Symbols.OperatorNegate, out ret) &&
- ret != NotImplementedType.Value) {
- return ret;
- }
-
- throw PythonOps.TypeError("bad operand type for unary -");
- }
-
- public static bool IsSubClass(PythonType/*!*/ c, PythonType/*!*/ typeinfo) {
- Assert.NotNull(c, typeinfo);
-
- if (typeinfo.UnderlyingSystemType.IsInterface) {
- // interfaces aren't in bases, and therefore IsSubclassOf doesn't do this check.
- if (typeinfo.UnderlyingSystemType.IsAssignableFrom(c.UnderlyingSystemType)) {
- return true;
- }
- }
-
- return c.IsSubclassOf(typeinfo);
- }
-
- public static bool IsSubClass(PythonType c, object typeinfo) {
- if (c == null) throw PythonOps.TypeError("issubclass: arg 1 must be a class");
- if (typeinfo == null) throw PythonOps.TypeError("issubclass: arg 2 must be a class");
-
- PythonTuple pt = typeinfo as PythonTuple;
- if (pt != null) {
- // Recursively inspect nested tuple(s)
- foreach (object o in pt) {
- try {
- FunctionPushFrame();
- if (IsSubClass(c, o)) {
- return true;
- }
- } finally {
- FunctionPopFrame();
- }
- }
- return false;
- }
-
- OldClass oc = typeinfo as OldClass;
- if (oc != null) {
- return c.IsSubclassOf(oc.TypeObject);
- }
-
- Type t = typeinfo as Type;
- if (t != null) {
- typeinfo = DynamicHelpers.GetPythonTypeFromType(t);
- }
-
- object bases;
- PythonType dt = typeinfo as PythonType;
- if (dt == null) {
- if (!PythonOps.TryGetBoundAttr(typeinfo, Symbols.Bases, out bases)) {
- //!!! deal with classes w/ just __bases__ defined.
- throw PythonOps.TypeErrorForBadInstance("issubclass(): {0} is not a class nor a tuple of classes", typeinfo);
- }
-
- IEnumerator ie = PythonOps.GetEnumerator(bases);
- while (ie.MoveNext()) {
- PythonType baseType = ie.Current as PythonType;
-
- if (baseType == null) {
- OldClass ocType = ie.Current as OldClass;
- if (ocType == null) throw PythonOps.TypeError("expected type, got {0}", DynamicHelpers.GetPythonType(ie.Current));
-
- baseType = ocType.TypeObject;
- }
-
- if (c.IsSubclassOf(baseType)) return true;
- }
- return false;
- }
-
- return IsSubClass(c, dt);
- }
-
- public static bool IsInstance(object o, PythonType typeinfo) {
- PythonType odt = DynamicHelpers.GetPythonType(o);
- if (IsSubClass(odt, typeinfo)) {
- return true;
- }
-
- return IsInstanceDynamic(o, typeinfo, odt);
- }
-
- public static bool IsInstance(object o, PythonTuple typeinfo) {
- foreach (object type in typeinfo) {
- try {
- PythonOps.FunctionPushFrame();
- if (type is PythonType) {
- if (IsInstance(o, (PythonType)type)) {
- return true;
- }
- } else if (type is PythonTuple) {
- if (IsInstance(o, (PythonTuple)type)) {
- return true;
- }
- } else if (IsInstance(o, type)) {
- return true;
- }
- } finally {
- PythonOps.FunctionPopFrame();
- }
- }
- return false;
- }
-
- public static bool IsInstance(object o, object typeinfo) {
- if (typeinfo == null) throw PythonOps.TypeError("isinstance: arg 2 must be a class, type, or tuple of classes and types");
-
- PythonTuple tt = typeinfo as PythonTuple;
- if (tt != null) {
- return IsInstance(o, tt);
- }
-
- if (typeinfo is OldClass) {
- // old instances are strange - they all share a common type
- // of instance but they can "be subclasses" of other
- // OldClass's. To check their types we need the actual
- // instance.
- OldInstance oi = o as OldInstance;
- if (oi != null) return oi._class.IsSubclassOf(typeinfo);
- }
-
- PythonType odt = DynamicHelpers.GetPythonType(o);
- if (IsSubClass(odt, typeinfo)) {
- return true;
- }
-
- return IsInstanceDynamic(o, typeinfo);
- }
-
- private static bool IsInstanceDynamic(object o, object typeinfo) {
- return IsInstanceDynamic(o, typeinfo, DynamicHelpers.GetPythonType(o));
- }
-
- private static bool IsInstanceDynamic(object o, object typeinfo, PythonType odt) {
- if (o is IPythonObject || o is OldInstance) {
- object cls;
- if (PythonOps.TryGetBoundAttr(o, Symbols.Class, out cls) &&
- (!object.ReferenceEquals(odt, cls))) {
- return IsSubclassSlow(cls, typeinfo);
- }
- }
- return false;
- }
-
- private static bool IsSubclassSlow(object cls, object typeinfo) {
- Debug.Assert(typeinfo != null);
- if (cls == null) return false;
-
- // Same type
- if (cls.Equals(typeinfo)) {
- return true;
- }
-
- // Get bases
- object bases;
- if (!PythonOps.TryGetBoundAttr(cls, Symbols.Bases, out bases)) {
- return false; // no bases, cannot be subclass
- }
- PythonTuple tbases = bases as PythonTuple;
- if (tbases == null) {
- return false; // not a tuple, cannot be subclass
- }
-
- foreach (object baseclass in tbases) {
- if (IsSubclassSlow(baseclass, typeinfo)) return true;
- }
-
- return false;
- }
-
- public static object OnesComplement(object o) {
- if (o is int) return ~(int)o;
- if (o is long) return ~(long)o;
- if (o is BigInteger) return ~((BigInteger)o);
- if (o is bool) return RuntimeHelpers.Int32ToObject((bool)o ? -2 : -1);
-
- object ret;
- if (PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default, o, Symbols.OperatorOnesComplement, out ret) &&
- ret != NotImplementedType.Value)
- return ret;
-
-
- throw PythonOps.TypeError("bad operand type for unary ~");
- }
-
- public static object Not(object o) {
- return IsTrue(o) ? RuntimeHelpers.False : RuntimeHelpers.True;
- }
-
- public static object Is(object x, object y) {
- return x == y ? RuntimeHelpers.True : RuntimeHelpers.False;
- }
-
- public static bool IsRetBool(object x, object y) {
- return x == y;
- }
-
- public static object IsNot(object x, object y) {
- return x != y ? RuntimeHelpers.True : RuntimeHelpers.False;
- }
-
- public static bool IsNotRetBool(object x, object y) {
- return x != y;
- }
-
- internal delegate T MultiplySequenceWorker<T>(T self, int count);
-
- /// <summary>
- /// Wraps up all the semantics of multiplying sequences so that all of our sequences
- /// don't duplicate the same logic. When multiplying sequences we need to deal with
- /// only multiplying by valid sequence types (ints, not floats), support coercion
- /// to integers if the type supports it, not multiplying by None, and getting the
- /// right semantics for multiplying by negative numbers and 1 (w/ and w/o subclasses).
- ///
- /// This function assumes that it is only called for case where count is not implicitly
- /// coercible to int so that check is skipped.
- /// </summary>
- internal static object MultiplySequence<T>(MultiplySequenceWorker<T> multiplier, T sequence, Index count, bool isForward) {
- if (isForward && count != null) {
- object ret;
- if (PythonTypeOps.TryInvokeBinaryOperator(DefaultContext.Default, count.Value, sequence, Symbols.OperatorReverseMultiply, out ret)) {
- if (ret != NotImplementedType.Value) return ret;
- }
- }
-
- int icount = GetSequenceMultiplier(sequence, count.Value);
-
- if (icount < 0) icount = 0;
- return multiplier(sequence, icount);
- }
-
- internal static int GetSequenceMultiplier(object sequence, object count) {
- int icount;
- if (!Converter.TryConvertToIndex(count, out icount)) {
- PythonTuple pt = null;
- if (count is OldInstance || !DynamicHelpers.GetPythonType(count).IsSystemType) {
- pt = Builtin.TryCoerce(DefaultContext.Default, count, sequence) as PythonTuple;
- }
-
- if (pt == null || !Converter.TryConvertToIndex(pt[0], out icount)) {
- throw TypeError("can't multiply sequence by non-int of type '{0}'", DynamicHelpers.GetPythonType(count).Name);
- }
- }
- return icount;
- }
-
- public static object Equal(CodeContext/*!*/ context, object x, object y) {
- PythonContext pc = PythonContext.GetContext(context);
- return pc.EqualSite.Target(pc.EqualSite, x, y);
- }
-
- public static bool EqualRetBool(object x, object y) {
- //TODO just can't seem to shake these fast paths
- if (x is int && y is int) { return ((int)x) == ((int)y); }
- if (x is string && y is string) { return ((string)x).Equals((string)y); }
-
- return DynamicHelpers.GetPythonType(x).EqualRetBool(x, y);
- }
-
- public static bool EqualRetBool(CodeContext/*!*/ context, object x, object y) {
- //TODO just can't seem to shake these fast paths
- if (x is int && y is int) { return ((int)x) == ((int)y); }
- if (x is string && y is string) { return ((string)x).Equals((string)y); }
-
- return DynamicHelpers.GetPythonType(x).EqualRetBool(x, y);
- }
-
- public static int Compare(object x, object y) {
- return Compare(DefaultContext.Default, x, y);
- }
-
- public static int Compare(CodeContext/*!*/ context, object x, object y) {
- if (x == y) return 0;
-
- return DynamicHelpers.GetPythonType(x).Compare(x, y);
- }
-
- public static object CompareEqual(int res) {
- return res == 0 ? RuntimeHelpers.True : RuntimeHelpers.False;
- }
-
- public static object CompareNotEqual(int res) {
- return res == 0 ? RuntimeHelpers.False : RuntimeHelpers.True;
- }
-
- public static object CompareGreaterThan(int res) {
- return res > 0 ? RuntimeHelpers.True : RuntimeHelpers.False;
- }
-
- public static object CompareGreaterThanOrEqual(int res) {
- return res >= 0 ? RuntimeHelpers.True : RuntimeHelpers.False;
- }
-
- public static object CompareLessThan(int res) {
- return res < 0 ? RuntimeHelpers.True : RuntimeHelpers.False;
- }
-
- public static object CompareLessThanOrEqual(int res) {
- return res <= 0 ? RuntimeHelpers.True : RuntimeHelpers.False;
- }
-
- public static bool CompareTypesEqual(object x, object y) {
- if (x == null && y == null) return true;
- if (x == null) return false;
- if (y == null) return false;
-
- if (DynamicHelpers.GetPythonType(x) == DynamicHelpers.GetPythonType(y)) {
- // avoid going to the ID dispenser if we have the same types...
- return x == y;
- }
-
- return PythonOps.CompareTypes(x, y) == 0;
- }
-
- public static bool CompareTypesNotEqual(object x, object y) {
- return PythonOps.CompareTypes(x, y) != 0;
- }
-
- public static bool CompareTypesGreaterThan(object x, object y) {
- return PythonOps.CompareTypes(x, y) > 0;
- }
-
- public static bool CompareTypesLessThan(object x, object y) {
- return PythonOps.CompareTypes(x, y) < 0;
- }
-
- public static bool CompareTypesGreaterThanOrEqual(object x, object y) {
- return PythonOps.CompareTypes(x, y) >= 0;
- }
-
- public static bool CompareTypesLessThanOrEqual(object x, object y) {
- return PythonOps.CompareTypes(x, y) <= 0;
- }
-
- public static int CompareTypes(object x, object y) {
- if (x == null && y == null) return 0;
- if (x == null) return -1;
- if (y == null) return 1;
-
- string name1, name2;
- int diff;
-
- if (DynamicHelpers.GetPythonType(x) != DynamicHelpers.GetPythonType(y)) {
- if (x.GetType() == typeof(OldInstance)) {
- name1 = ((OldInstance)x)._class.__name__;
- if (y.GetType() == typeof(OldInstance)) {
- name2 = ((OldInstance)y)._class.__name__;
- } else {
- // old instances are always less than new-style classes
- return -1;
- }
- } else if (y.GetType() == typeof(OldInstance)) {
- // old instances are always less than new-style classes
- return 1;
- } else {
- name1 = PythonTypeOps.GetName(x);
- name2 = PythonTypeOps.GetName(y);
- }
- diff = String.CompareOrdinal(name1, name2);
- if (diff == 0) {
- // if the types are different but have the same name compare based upon their types.
- diff = (int)(IdDispenser.GetId(DynamicHelpers.GetPythonType(x)) - IdDispenser.GetId(DynamicHelpers.GetPythonType(y)));
- }
- } else {
- diff = (int)(IdDispenser.GetId(x) - IdDispenser.GetId(y));
- }
-
- if (diff < 0) return -1;
- if (diff == 0) return 0;
- return 1;
- }
-
- public static object GreaterThanHelper(CodeContext/*!*/ context, object self, object other) {
- return InternalCompare(context, Operators.GreaterThan, self, other);
- }
-
- public static object LessThanHelper(CodeContext/*!*/ context, object self, object other) {
- return InternalCompare(context, Operators.LessThan, self, other);
- }
-
- public static object GreaterThanOrEqualHelper(CodeContext/*!*/ context, object self, object other) {
- return InternalCompare(context, Operators.GreaterThanOrEqual, self, other);
- }
-
- public static object LessThanOrEqualHelper(CodeContext/*!*/ context, object self, object other) {
- return InternalCompare(context, Operators.LessThanOrEqual, self, other);
- }
-
- public static object InternalCompare(CodeContext/*!*/ context, Operators op, object self, object other) {
- object ret;
- if (PythonTypeOps.TryInvokeBinaryOperator(context, self, other, Symbols.OperatorToSymbol(op), out ret))
- return ret;
-
- return NotImplementedType.Value;
- }
-
- public static int CompareToZero(object value) {
- double val;
- if (Converter.TryConvertToDouble(value, out val)) {
- if (val > 0) return 1;
- if (val < 0) return -1;
- return 0;
- }
- throw PythonOps.TypeErrorForBadInstance("an integer is required (got {0})", value);
- }
-
- public static int CompareArrays(object[] data0, int size0, object[] data1, int size1) {
- int size = Math.Min(size0, size1);
- for (int i = 0; i < size; i++) {
- int c = PythonOps.Compare(data0[i], data1[i]);
- if (c != 0) return c;
- }
- if (size0 == size1) return 0;
- return size0 > size1 ? +1 : -1;
- }
-
- public static object PowerMod(CodeContext/*!*/ context, object x, object y, object z) {
- object ret;
- if (z == null) {
- return PythonContext.GetContext(context).Operation(StandardOperators.Power, x, y);
- }
- if (x is int && y is int && z is int) {
- ret = Int32Ops.Power((int)x, (int)y, (int)z);
- if (ret != NotImplementedType.Value) return ret;
- } else if (x is BigInteger) {
- ret = BigIntegerOps.Power((BigInteger)x, y, z);
- if (ret != NotImplementedType.Value) return ret;
- }
-
- if (x is Complex64 || y is Complex64 || z is Complex64) {
- throw PythonOps.ValueError("complex modulo");
- }
-
- if (PythonTypeOps.TryInvokeTernaryOperator(context, x, y, z, Symbols.OperatorPower, out ret)) {
- if(ret != NotImplementedType.Value) {
- return ret;
- } else if (!IsNumericObject(y) || !IsNumericObject(z)) {
- // special error message in this case...
- throw TypeError("pow() 3rd argument not allowed unless all arguments are integers");
- }
- }
-
- throw PythonOps.TypeErrorForBinaryOp("power with modulus", x, y);
- }
-
- public static ICollection GetCollection(object o) {
- ICollection ret = o as ICollection;
- if (ret != null) return ret;
-
- List<object> al = new List<object>();
- IEnumerator e = GetEnumerator(o);
- while (e.MoveNext()) al.Add(e.Current);
- return al;
- }
-
- public static IEnumerator GetEnumerator(object o) {
- IEnumerator ie;
- if (!TryGetEnumerator(DefaultContext.Default, o, out ie)) {
- throw PythonOps.TypeError("{0} is not enumerable", PythonTypeOps.GetName(o));
- }
- return ie;
- }
-
- public static IEnumerator GetEnumeratorForUnpack(CodeContext/*!*/ context, object enumerable) {
- IEnumerator enumerator;
- if (!TryGetEnumerator(context, enumerable, out enumerator)) {
- throw PythonOps.TypeError("'{0}' object is not iterable", PythonTypeOps.GetName(enumerable));
- }
-
- return enumerator;
- }
-
- public static long Id(object o) {
- return IdDispenser.GetId(o);
- }
-
- public static string HexId(object o) {
- return string.Format("0x{0:X16}", Id(o));
- }
-
- // For hash operators, it's essential that:
- // Cmp(x,y)==0 implies hash(x) == hash(y)
- //
- // Equality is a language semantic determined by the Python's numerical Compare() ops
- // in IronPython.Runtime.Operations namespaces.
- // For example, the CLR compares float(1.0) and int32(1) as different, but Python
- // compares them as equal. So Hash(1.0f) and Hash(1) must be equal.
- //
- // Python allows an equality relationship between int, double, BigInteger, and complex.
- // So each of these hash functions must be aware of their possible equality relationships
- // and hash appropriately.
- //
- // Types which differ in hashing from .NET have __hash__ functions defined in their
- // ops classes which do the appropriate hashing.
- public static int Hash(CodeContext/*!*/ context, object o) {
- return PythonContext.GetContext(context).Hash(o);
- }
-
- public static object Hex(object o) {
- if (o is int) return Int32Ops.__hex__((int)o);
- else if (o is BigInteger) return BigIntegerOps.__hex__((BigInteger)o);
-
- object hex;
- if(PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default,
- o,
- Symbols.ConvertToHex,
- out hex)) {
- if (!(hex is string) && !(hex is ExtensibleString))
- throw PythonOps.TypeError("hex expected string type as return, got '{0}'", PythonTypeOps.GetName(hex));
-
- return hex;
- }
- throw TypeError("hex() argument cannot be converted to hex");
- }
-
- public static object Oct(object o) {
- if (o is int) {
- return Int32Ops.__oct__((int)o);
- } else if (o is BigInteger) {
- return BigIntegerOps.__oct__((BigInteger)o);
- }
-
- object octal;
-
- if(PythonTypeOps.TryInvokeUnaryOperator(DefaultContext.Default,
- o,
- Symbols.ConvertToOctal,
- out octal)) {
- if (!(octal is string) && !(octal is ExtensibleString))
- throw PythonOps.TypeError("hex expected string type as return, got '{0}'", PythonTypeOps.GetName(octal));
-
- return octal;
- }
- throw TypeError("oct() argument cannot be converted to octal");
- }
-
- public static int Length(object o) {
- string s = o as String;
- if (s != null) return s.Length;
-
- ICollection ic = o as ICollection;
- if (ic != null) return ic.Count;
-
- object len = PythonContext.InvokeUnaryOperator(DefaultContext.Default, UnaryOperators.Length, o, "len() of unsized object");
-
- int res;
- if (len is int) {
- res = (int)len;
- } else {
- res = Converter.ConvertToInt32(len);
- }
-
- if (res < 0) {
- throw PythonOps.ValueError("__len__ should return >= 0, got {0}", res);
- }
- return res;
- }
-
- public static object CallWithContext(CodeContext/*!*/ context, object func, params object[] args) {
- return PythonCalls.Call(context, func, args);
- }
-
- /// <summary>
- /// Supports calling of functions that require an explicit 'this'
- /// Currently, we check if the function object implements the interface
- /// that supports calling with 'this'. If not, the 'this' object is dropped
- /// and a normal call is made.
- /// </summary>
- public static object CallWithContextAndThis(CodeContext/*!*/ context, object func, object instance, params object[] args) {
- // drop the 'this' and make the call
- return CallWithContext(context, func, args);
- }
-
- public static object ToPythonType(PythonType dt) {
- if (dt != null) {
- return ((object)dt.OldClass) ?? ((object)dt);
- }
- return null;
- }
-
- public static object CallWithArgsTupleAndContext(CodeContext/*!*/ context, object func, object[] args, object argsTuple) {
- PythonTuple tp = argsTuple as PythonTuple;
- if (tp != null) {
- object[] nargs = new object[args.Length + tp.__len__()];
- for (int i = 0; i < args.Length; i++) nargs[i] = args[i];
- for (int i = 0; i < tp.__len__(); i++) nargs[i + args.Length] = tp[i];
- return CallWithContext(context, func, nargs);
- }
-
- List allArgs = PythonOps.MakeEmptyList(args.Length + 10);
- allArgs.AddRange(args);
- IEnumerator e = PythonOps.GetEnumerator(argsTuple);
- while (e.MoveNext()) allArgs.AddNoLock(e.Current);
-
- return CallWithContext(context, func, allArgs.GetObjectArray());
- }
-
- public static object CallWithArgsTupleAndKeywordDictAndContext(CodeContext/*!*/ context, object func, object[] args, string[] names, object argsTuple, object kwDict) {
- IDictionary kws = kwDict as IDictionary;
- if (kws == null && kwDict != null) throw PythonOps.TypeError("argument after ** must be a dictionary");
-
- if ((kws == null || kws.Count == 0) && names.Length == 0) {
- List<object> largs = new List<object>(args);
- if (argsTuple != null) {
- foreach(object arg in PythonOps.GetCollection(argsTuple))
- largs.Add(arg);
- }
- return CallWithContext(context, func, largs.ToArray());
- } else {
- List<object> largs;
-
- if (argsTuple != null && args.Length == names.Length) {
- PythonTuple tuple = argsTuple as PythonTuple;
- if (tuple == null) tuple = new PythonTuple(argsTuple);
-
- largs = new List<object>(tuple);
- largs.AddRange(args);
- } else {
- largs = new List<object>(args);
- if (argsTuple != null) {
- largs.InsertRange(args.Length - names.Length, PythonTuple.Make(argsTuple));
- }
- }
-
- List<string> lnames = new List<string>(names);
-
- if (kws != null) {
- IDictionaryEnumerator ide = kws.GetEnumerator();
- while (ide.MoveNext()) {
- lnames.Add((string)ide.Key);
- largs.Add(ide.Value);
- }
- }
-
- return PythonCalls.CallWithKeywordArgs(context, func, largs.ToArray(), lnames.ToArray());
- }
- }
-
- public static object CallWithKeywordArgs(CodeContext/*!*/ context, object func, object[] args, string[] names) {
- return PythonCalls.CallWithKeywordArgs(context, func, args, names);
- }
-
- public static object CallWithArgsTuple(object func, object[] args, object argsTuple) {
- PythonTuple tp = argsTuple as PythonTuple;
- if (tp != null) {
- object[] nargs = new object[args.Length + tp.__len__()];
- for (int i = 0; i < args.Length; i++) nargs[i] = args[i];
- for (int i = 0; i < tp.__len__(); i++) nargs[i + args.Length] = tp[i];
- return PythonCalls.Call(func, nargs);
- }
-
- List allArgs = PythonOps.MakeEmptyList(args.Length + 10);
- allArgs.AddRange(args);
- IEnumerator e = PythonOps.GetEnumerator(argsTuple);
- while (e.MoveNext()) allArgs.AddNoLock(e.Current);
-
- return PythonCalls.Call(func, allArgs.GetObjectArray());
- }
-
- public static object GetIndex(CodeContext/*!*/ context, object o, object index) {
- PythonContext pc = PythonContext.GetContext(context);
- return pc.GetIndexSite.Target(pc.GetIndexSite, o, index);
- }
-
- public static bool TryGetBoundAttr(object o, SymbolId name, out object ret) {
- return TryGetBoundAttr(DefaultContext.Default, o, name, out ret);
- }
-
- class AttrKey : IEquatable<AttrKey> {
- private Type _type;
- private SymbolId _name;
-
- public AttrKey(Type type, SymbolId name) {
- _type = type;
- _name = name;
- }
-
- #region IEquatable<AttrKey> Members
-
- public bool Equals(AttrKey other) {
- if (other == null) return false;
-
- return _type == other._type && _name == other._name;
- }
-
- #endregion
-
- public override bool Equals(object obj) {
- return Equals(obj as AttrKey);
- }
-
- public override int GetHashCode() {
- return _type.GetHashCode() ^ _name.GetHashCode();
- }
- }
-
- public static void SetAttr(CodeContext/*!*/ context, object o, SymbolId name, object value) {
- PythonContext.GetContext(context).SetAttr(context, o, name, value);
- }
-
- public static bool TryGetBoundAttr(CodeContext/*!*/ context, object o, SymbolId name, out object ret) {
- return DynamicHelpers.GetPythonType(o).TryGetBoundAttr(context, o, name, out ret);
- }
-
- public static void DeleteAttr(CodeContext/*!*/ context, object o, SymbolId name) {
- PythonContext.GetContext(context).DeleteAttr(context, o, name);
- }
-
- public static bool HasAttr(CodeContext/*!*/ context, object o, SymbolId name) {
- object dummy;
- try {
- return TryGetBoundAttr(context, o, name, out dummy);
- } catch {
- return false;
- }
- }
-
- public static object GetBoundAttr(CodeContext/*!*/ context, object o, SymbolId name) {
- object ret;
- if (!DynamicHelpers.GetPythonType(o).TryGetBoundAttr(context, o, name, out ret)) {
- if (o is OldClass) {
- throw PythonOps.AttributeError("type object '{0}' has no attribute '{1}'",
- ((OldClass)o).__name__, SymbolTable.IdToString(name));
- } else {
- throw PythonOps.AttributeError("'{0}' object has no attribute '{1}'", DynamicHelpers.GetPythonType(o).Name, SymbolTable.IdToString(name));
- }
- }
-
- return ret;
- }
-
- public static void ObjectSetAttribute(CodeContext/*!*/ context, object o, SymbolId name, object value) {
- if (!DynamicHelpers.GetPythonType(o).TrySetNonCustomMember(context, o, name, value))
- throw AttributeErrorForMissingOrReadonly(context, DynamicHelpers.GetPythonType(o), name);
- }
-
- public static void ObjectDeleteAttribute(CodeContext/*!*/ context, object o, SymbolId name) {
- object dummy;
- if (!PythonTypeOps.TryInvokeBinaryOperator(context, o, name, Symbols.DeleteDescriptor, out dummy)) {
- throw AttributeErrorForMissingOrReadonly(context, DynamicHelpers.GetPythonType(o), name);
- }
- }
-
- public static object ObjectGetAttribute(CodeContext/*!*/ context, object o, SymbolId name) {
- OldClass oc = o as OldClass;
- if (oc != null) {
- return oc.GetMember(context, name);
- }
-
- object value;
- if (DynamicHelpers.GetPythonType(o).TryGetNonCustomMember(context, o, name, out value)) {
- return value;
- }
-
- throw PythonOps.AttributeErrorForMissingAttribute(DynamicHelpers.GetPythonType(o).Name, name);
- }
-
- public static IList<object> GetAttrNames(CodeContext/*!*/ context, object o) {
-
- IMembersList memList = o as IMembersList;
- if (memList != null) {
- return memList.GetMemberNames(context);
- }
-
- List res;
- if (o is IDynamicObject) {
- res = new List();
-
- PythonContext pc = PythonContext.GetContext(context);
- foreach (object x in pc.MemberNamesSite.Target.Invoke(pc.MemberNamesSite, context, o)) {
- res.AddNoLock(x);
- }
- } else {
- res = DynamicHelpers.GetPythonType(o).GetMemberNames(context, o);
-
- #if !SILVERLIGHT
- if (o != null && ComOps.IsComObject(o)) {
- foreach (string name in Microsoft.Scripting.Com.ComObject.ObjectToComObject(o).MemberNames) {
- if (!res.Contains(name)) {
- res.AddNoLock(name);
- }
- }
- }
- #endif
- }
-
- //!!! ugly, we need to check for non-SymbolID keys
- IPythonObject dyno = o as IPythonObject;
- if (dyno != null) {
- IAttributesCollection iac = dyno.Dict;
- if (iac != null) {
- foreach (object id in iac.Keys) {
- if (!res.__contains__(id)) res.append(id);
- }
- }
- }
-
- return res;
- }
-
- public static IDictionary<object, object> GetAttrDict(CodeContext/*!*/ context, object o) {
- IAttributesCollection iac = DynamicHelpers.GetPythonType(o).GetMemberDictionary(context, o);
- if (iac != null) {
- return iac.AsObjectKeyedDictionary();
- }
- throw PythonOps.AttributeErrorForMissingAttribute(PythonTypeOps.GetName(o), Symbols.Dict);
- }
-
- /// <summary>
- /// Called from generated code emitted by NewTypeMaker.
- /// </summary>
- public static void CheckInitializedAttribute(object o, object self, string name) {
- if (o == Uninitialized.Instance) {
- throw PythonOps.AttributeError("'{0}' object has no attribute '{1}'",
- DynamicHelpers.GetPythonType(self),
- name);
- }
- }
-
- /// <summary>
- /// Handles the descriptor protocol for user-defined objects that may implement __get__
- /// </summary>
- public static object GetUserDescriptor(object o, object instance, object context) {
- if (o != null && o.GetType() == typeof(OldInstance)) return o; // only new-style classes can have descriptors
- if (o is IPythonObject) {
- // slow, but only encountred for user defined descriptors.
- PerfTrack.NoteEvent(PerfTrack.Categories.DictInvoke, "__get__");
- object ret;
- if (PythonContext.TryInvokeTernaryOperator(DefaultContext.Default,
- TernaryOperators.GetDescriptor,
- o,
- instance,
- context,
- out ret)) {
- return ret;
- }
- }
-
- return o;
- }
-
- /// <summary>
- /// Handles the descriptor protocol for user-defined objects that may implement __set__
- /// </summary>
- public static bool TrySetUserDescriptor(object o, object instance, object value) {
- if (o != null && o.GetType() == typeof(OldInstance)) return false; // only new-style classes have descriptors
-
- // slow, but only encountred for user defined descriptors.
- PerfTrack.NoteEvent(PerfTrack.Categories.DictInvoke, "__set__");
-
- object dummy;
- return PythonContext.TryInvokeTernaryOperator(DefaultContext.Default,
- TernaryOperators.SetDescriptor,
- o,
- instance,
- value,
- out dummy);
- }
-
- /// <summary>
- /// Handles the descriptor protocol for user-defined objects that may implement __delete__
- /// </summary>
- public static bool TryDeleteUserDescriptor(object o, object instance) {
- if (o != null && o.GetType() == typeof(OldInstance)) return false; // only new-style classes can have descriptors
-
- // slow, but only encountred for user defined descriptors.
- PerfTrack.NoteEvent(PerfTrack.Categories.DictInvoke, "__delete__");
-
- object dummy;
- return PythonTypeOps.TryInvokeBinaryOperator(DefaultContext.Default,
- o,
- instance,
- Symbols.DeleteDescriptor,
- out dummy);
- }
-
- public static object Invoke(CodeContext/*!*/ context, object target, SymbolId name, params object[] args) {
- return PythonCalls.Call(context, PythonOps.GetBoundAttr(context, target, name), args);
- }
-
- public static Delegate CreateDynamicDelegate(DynamicMethod meth, Type delegateType, object target) {
- // Always close delegate around its own instance of the frame
- return meth.CreateDelegate(delegateType, target);
- }
-
- public static double CheckMath(double v) {
- if (double.IsInfinity(v)) {
- throw PythonOps.OverflowError("math range error");
- } else if (double.IsNaN(v)) {
- throw PythonOps.ValueError("math domain error");
- } else {
- return v;
- }
- }
-
- public static object IsMappingType(CodeContext/*!*/ context, object o) {
- if (o is IDictionary || o is PythonDictionary || o is IDictionary<object, object> || o is IAttributesCollection) {
- return RuntimeHelpers.True;
- }
- object getitem;
- if ((o is IPythonObject || o is OldInstance) && PythonOps.TryGetBoundAttr(context, o, Symbols.GetItem, out getitem)) {
- if (!PythonOps.IsClsVisible(context)) {
- // in standard Python methods aren't mapping types, therefore
- // if the user hasn't broken out of that box yet don't treat
- // them as mapping types.
- if (o is BuiltinFunction) return RuntimeHelpers.False;
- }
- return RuntimeHelpers.True;
- }
- return RuntimeHelpers.False;
- }
-
- public static int FixSliceIndex(int v, int len) {
- if (v < 0) v = len + v;
- if (v < 0) return 0;
- if (v > len) return len;
- return v;
- }
-
- public static void FixSlice(int length, object start, object stop, object step,
- out int ostart, out int ostop, out int ostep, out int ocount) {
- if (step == null) {
- ostep = 1;
- } else {
- ostep = Converter.ConvertToIndex(step);
- if (ostep == 0) {
- throw PythonOps.ValueError("step cannot be zero");
- }
- }
-
- if (start == null) {
- ostart = ostep > 0 ? 0 : length - 1;
- } else {
- ostart = Converter.ConvertToIndex(start);
- if (ostart < 0) {
- ostart += length;
- if (ostart < 0) {
- ostart = ostep > 0 ? Math.Min(length, 0) : Math.…
Large files files are truncated, but you can click here to view the full file