示例#1
0
        public static int GetValueHashCodeHelper(object self)
        {
            // new-style classes only lookup in slots, not in instance
            // members
            object func;

            if (DynamicHelpers.GetPythonType(self).TryGetBoundMember(DefaultContext.Default, self, "__hash__", out func))
            {
                return(Converter.ConvertToInt32(PythonCalls.Call(func)));
            }

            return(self.GetHashCode());
        }
示例#2
0
        internal static bool TryInvokeTernaryOperator(CodeContext context, object o, object arg1, object arg2, string name, out object value)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Temporary, "TernaryOp " + CompilerHelpers.GetType(o).Name + " " + name);

            if (TryGetOperator(context, o, name, out object callable))
            {
                value = PythonCalls.Call(context, callable, arg1, arg2);
                return(true);
            }

            value = null;
            return(false);
        }
示例#3
0
        internal static PythonTuple ReduceProtocol0(CodeContext /*!*/ context, object self)
        {
            // CPython implements this in copyreg._reduce_ex

            PythonType myType = DynamicHelpers.GetPythonType(self); // PEP 307 calls this "D"

            ThrowIfNativelyPickable(myType);

            object?getState;
            bool   hasGetState = PythonOps.TryGetBoundAttr(context, self, "__getstate__", out getState);

            if (PythonOps.TryGetBoundAttr(context, myType, "__slots__", out object?slots) && PythonOps.Length(slots) > 0 && !hasGetState)
            {
                // ??? does this work with superclass slots?
                throw PythonOps.TypeError("a class that defines __slots__ without defining __getstate__ cannot be pickled with protocols 0 or 1");
            }

            PythonType closestNonPythonBase = FindClosestNonPythonBase(myType); // PEP 307 calls this "B"

            object func = context.LanguageContext.PythonReconstructor;

            object funcArgs = PythonTuple.MakeTuple(
                myType,
                closestNonPythonBase,
                TypeCache.Object == closestNonPythonBase ? null : PythonCalls.Call(context, closestNonPythonBase, self)
                );

            object?state;

            if (hasGetState)
            {
                state = PythonOps.CallWithContext(context, getState);
            }
            else
            {
                if (self is IPythonObject ipo)
                {
                    state = ipo.Dict;
                }
                else if (!PythonOps.TryGetBoundAttr(context, self, "__dict__", out state))
                {
                    state = null;
                }
            }
            if (!PythonOps.IsTrue(state))
            {
                state = null;
            }

            return(PythonTuple.MakeTuple(func, funcArgs, state));
        }
示例#4
0
        internal static bool TryInvokeTernaryOperator(CodeContext context, object o, object arg1, object arg2, string name, out object value)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Temporary, "TernaryOp " + CompilerHelpers.GetType(o).Name + " " + name);

            PythonTypeSlot pts;
            PythonType     pt = DynamicHelpers.GetPythonType(o);
            object         callable;

            if (pt.TryResolveSlot(context, name, out pts) &&
                pts.TryGetValue(context, o, pt, out callable))
            {
                value = PythonCalls.Call(context, callable, arg1, arg2);
                return(true);
            }

            value = null;
            return(false);
        }
示例#5
0
        internal static object CallWorker(CodeContext /*!*/ context, PythonType dt, KwCallInfo args)
        {
            object[] clsArgs   = ArrayUtils.Insert <object>(dt, args.Arguments);
            object   newObject = PythonCalls.CallWithKeywordArgs(context,
                                                                 GetTypeNew(context, dt),
                                                                 clsArgs,
                                                                 args.Names);

            if (newObject == null)
            {
                return(null);
            }

            if (ShouldInvokeInit(dt, DynamicHelpers.GetPythonType(newObject), args.Arguments.Length))
            {
                PythonCalls.CallWithKeywordArgs(context, GetInitMethod(context, dt, newObject), args.Arguments, args.Names);

                AddFinalizer(context, dt, newObject);
            }

            return(newObject);
        }
示例#6
0
        public static void AddRemoveEventHelper(object method, IPythonObject instance, object eventValue, string name)
        {
            object callable = method;

            // TODO: dt gives us a PythonContext which we should use
            PythonType dt = instance.PythonType;

            if (method is PythonTypeSlot dts)
            {
                if (!dts.TryGetValue(DefaultContext.Default, instance, dt, out callable))
                {
                    throw PythonOps.AttributeErrorForMissingAttribute(dt.Name, name);
                }
            }

            if (!PythonOps.IsCallable(DefaultContext.Default, callable))
            {
                throw PythonOps.TypeError("Expected callable value for {0}, but found {1}", name.ToString(),
                                          PythonOps.GetPythonTypeName(method));
            }

            PythonCalls.Call(callable, eventValue);
        }
示例#7
0
        public static object fromhex(CodeContext /*!*/ context, PythonType /*!*/ cls, string self)
        {
            if (String.IsNullOrEmpty(self))
            {
                throw PythonOps.ValueError("expected non empty string");
            }

            self = self.Trim(_whitespace);

            // look for inf, infinity, nan, etc...
            double?specialRes = TryParseSpecialFloat(self);

            if (specialRes != null)
            {
                return(specialRes.Value);
            }

            // nothing special, parse the hex...
            if (_fromHexRegex == null)
            {
                _fromHexRegex = new Regex("\\A\\s*(?<sign>[-+])?(?:0[xX])?(?<integer>[0-9a-fA-F]+)?(?<fraction>\\.[0-9a-fA-F]*)?(?<exponent>[pP][-+]?[0-9]+)?\\s*\\z");
            }
            Match match = _fromHexRegex.Match(self);

            if (!match.Success)
            {
                throw InvalidHexString();
            }

            var sign     = match.Groups["sign"];
            var integer  = match.Groups["integer"];
            var fraction = match.Groups["fraction"];
            var exponent = match.Groups["exponent"];

            bool isNegative = sign.Success && sign.Value == "-";

            BigInteger intVal;

            if (integer.Success)
            {
                intVal = LiteralParser.ParseBigInteger(integer.Value, 16);
            }
            else
            {
                intVal = BigInteger.Zero;
            }

            // combine the integer and fractional parts into one big int
            BigInteger finalBits;
            int        decimalPointBit = 0; // the number of bits of fractions that we have

            if (fraction.Success)
            {
                BigInteger fractionVal = 0;
                // add the fractional bits to the integer value
                for (int i = 1; i < fraction.Value.Length; i++)
                {
                    char chr = fraction.Value[i];
                    int  val;
                    if (chr >= '0' && chr <= '9')
                    {
                        val = chr - '0';
                    }
                    else if (chr >= 'a' && chr <= 'f')
                    {
                        val = 10 + chr - 'a';
                    }
                    else if (chr >= 'A' && chr <= 'Z')
                    {
                        val = 10 + chr - 'A';
                    }
                    else
                    {
                        // unreachable due to the regex
                        throw new InvalidOperationException();
                    }

                    fractionVal      = (fractionVal << 4) | val;
                    decimalPointBit += 4;
                }
                finalBits = (intVal << decimalPointBit) | fractionVal;
            }
            else
            {
                // we only have the integer value
                finalBits = intVal;
            }

            if (exponent.Success)
            {
                int exponentVal = 0;
                if (!Int32.TryParse(exponent.Value.Substring(1), out exponentVal))
                {
                    if (exponent.Value.ToLowerAsciiTriggered().StartsWith("p-") || finalBits == BigInteger.Zero)
                    {
                        double zeroRes = isNegative ? NegativeZero : PositiveZero;

                        if (cls == TypeCache.Double)
                        {
                            return(zeroRes);
                        }

                        return(PythonCalls.Call(cls, zeroRes));
                    }
                    // integer value is too big, no way we're fitting this in.
                    throw HexStringOverflow();
                }

                // update the bits to truly reflect the exponent
                if (exponentVal > 0)
                {
                    finalBits = finalBits << exponentVal;
                }
                else if (exponentVal < 0)
                {
                    decimalPointBit -= exponentVal;
                }
            }

            if ((!exponent.Success && !fraction.Success && !integer.Success) ||
                (!integer.Success && fraction.Length == 1))
            {
                throw PythonOps.ValueError("invalid hexidecimal floating point string '{0}'", self);
            }

            if (finalBits == BigInteger.Zero)
            {
                if (isNegative)
                {
                    return(NegativeZero);
                }
                else
                {
                    return(PositiveZero);
                }
            }

            int highBit = finalBits.GetBitCount();
            // minus 1 because we'll discard the high bit as it's implicit
            int finalExponent = highBit - decimalPointBit - 1;

            while (finalExponent < -1023)
            {
                // if we have a number with a very negative exponent
                // we'll throw away all of the insignificant bits even
                // if it takes the number down to zero.
                highBit++;
                finalExponent++;
            }

            if (finalExponent == -1023)
            {
                // the exponent bits will be all zero, we're going to be a denormalized number, so
                // we need to keep the most significant bit.
                highBit++;
            }

            // we have 52 bits to store the exponent.  In a normalized number the mantissa has an
            // implied 1 bit, in denormalized mode it doesn't.
            int  lostBits = highBit - 53;
            bool rounded  = false;

            if (lostBits > 0)
            {
                // we have more bits then we can stick in the double, we need to truncate or round the value.
                BigInteger finalBitsAndRoundingBit = finalBits >> (lostBits - 1);

                // check if we need to round up (round half even aka bankers rounding)
                if ((finalBitsAndRoundingBit & BigInteger.One) != BigInteger.Zero)
                {
                    // grab the bits we need and the least significant bit which we care about for rounding
                    BigInteger discardedBits = finalBits & ((BigInteger.One << (lostBits - 1)) - 1);

                    if (discardedBits != BigInteger.Zero ||                            // not exactly .5
                        ((finalBits >> lostBits) & BigInteger.One) != BigInteger.Zero) // or we're exactly .5 and odd and need to round up
                    // round the value up by adding 1
                    {
                        BigInteger roundedBits = finalBitsAndRoundingBit + 1;

                        // now remove the least significant bit we kept for rounding
                        finalBits = (roundedBits >> 1) & 0xfffffffffffff;

                        // check to see if we overflowed into the next bit (e.g. we had a pattern like ffffff rounding to 1000000)
                        if (roundedBits.GetBitCount() != finalBitsAndRoundingBit.GetBitCount())
                        {
                            if (finalExponent != -1023)
                            {
                                // we overflowed and we're a normalized number.  Discard the new least significant bit so we have
                                // the correct number of bits.  We need to raise the exponent to account for this division by 2.
                                finalBits = finalBits >> 1;
                                finalExponent++;
                            }
                            else if (finalBits == BigInteger.Zero)
                            {
                                // we overflowed and we're a denormalized number == 0.  Increase the exponent making us a normalized
                                // number.  Don't adjust the bits because we're now gaining an implicit 1 bit.
                                finalExponent++;
                            }
                        }

                        rounded = true;
                    }
                }
            }

            if (!rounded)
            {
                // no rounding is necessary, just shift the bits to get the mantissa
                finalBits = (finalBits >> (highBit - 53)) & 0xfffffffffffff;
            }
            if (finalExponent > 1023)
            {
                throw HexStringOverflow();
            }

            // finally assemble the bits
            long bits = (long)finalBits;

            bits |= (((long)finalExponent) + 1023) << 52;
            if (isNegative)
            {
                bits |= unchecked ((long)0x8000000000000000);
            }

            double res = BitConverter.Int64BitsToDouble(bits);

            if (cls == TypeCache.Double)
            {
                return(res);
            }

            return(PythonCalls.Call(cls, res));
        }