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()); }
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); }
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)); }
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); }
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); }
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); }
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)); }