github.com/pygolin/runtime@v0.0.0-20201208210830-a62e3cd39798/int.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package runtime 16 17 import ( 18 "fmt" 19 "math" 20 "math/big" 21 "reflect" 22 "strconv" 23 ) 24 25 const ( 26 internedIntMin = -2 27 internedIntMax = 300 28 ) 29 30 var ( 31 internedInts = makeInternedInts() 32 ) 33 34 // Int represents Python 'int' objects. 35 type Int struct { 36 Object 37 value int 38 } 39 40 // NewInt returns a new Int holding the given integer value. 41 func NewInt(value int) *Int { 42 if value >= internedIntMin && value <= internedIntMax { 43 return &internedInts[value-internedIntMin] 44 } 45 return &Int{Object{typ: IntType}, value} 46 } 47 48 func toIntUnsafe(o *Object) *Int { 49 return (*Int)(o.toPointer()) 50 } 51 52 // ToObject upcasts i to an Object. 53 func (i *Int) ToObject() *Object { 54 return &i.Object 55 } 56 57 // Value returns the underlying integer value held by i. 58 func (i *Int) Value() int { 59 return i.value 60 } 61 62 // IsTrue returns false if i is zero, true otherwise. 63 func (i *Int) IsTrue() bool { 64 return i.Value() != 0 65 } 66 67 // IntType is the object representing the Python 'int' type. 68 var IntType = newBasisType("int", reflect.TypeOf(Int{}), toIntUnsafe, ObjectType) 69 70 func intAbs(f *Frame, o *Object) (*Object, *BaseException) { 71 z := toIntUnsafe(o) 72 if z.Value() > 0 { 73 return z.ToObject(), nil 74 } 75 return intNeg(f, o) 76 } 77 78 func intAdd(f *Frame, v, w *Object) (*Object, *BaseException) { 79 return intAddMulOp(f, "__add__", v, w, intCheckedAdd, longAdd) 80 } 81 82 func intAnd(f *Frame, v, w *Object) (*Object, *BaseException) { 83 if !w.isInstance(IntType) { 84 return NotImplemented, nil 85 } 86 return NewInt(toIntUnsafe(v).Value() & toIntUnsafe(w).Value()).ToObject(), nil 87 } 88 89 func intDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 90 return intDivModOp(f, "__div__", v, w, intCheckedDiv, longDiv) 91 } 92 93 func intDivMod(f *Frame, v, w *Object) (*Object, *BaseException) { 94 return intDivAndModOp(f, "__divmod__", v, w, intCheckedDivMod, longDivAndMod) 95 } 96 97 func intEq(f *Frame, v, w *Object) (*Object, *BaseException) { 98 return intCompare(compareOpEq, toIntUnsafe(v), w), nil 99 } 100 101 func intGE(f *Frame, v, w *Object) (*Object, *BaseException) { 102 return intCompare(compareOpGE, toIntUnsafe(v), w), nil 103 } 104 105 func intGetNewArgs(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { 106 if raised := checkMethodArgs(f, "__getnewargs__", args, IntType); raised != nil { 107 return nil, raised 108 } 109 return NewTuple1(args[0]).ToObject(), nil 110 } 111 112 func intGT(f *Frame, v, w *Object) (*Object, *BaseException) { 113 return intCompare(compareOpGT, toIntUnsafe(v), w), nil 114 } 115 116 func intFloat(f *Frame, o *Object) (*Object, *BaseException) { 117 i := toIntUnsafe(o).Value() 118 return NewFloat(float64(i)).ToObject(), nil 119 } 120 121 func intHash(f *Frame, o *Object) (*Object, *BaseException) { 122 return o, nil 123 } 124 125 func intHex(f *Frame, o *Object) (*Object, *BaseException) { 126 val := numberToBase("0x", 16, o) 127 return NewStr(val).ToObject(), nil 128 } 129 130 func intIndex(f *Frame, o *Object) (*Object, *BaseException) { 131 return o, nil 132 } 133 134 func intInt(f *Frame, o *Object) (*Object, *BaseException) { 135 if o.typ == IntType { 136 return o, nil 137 } 138 return NewInt(toIntUnsafe(o).Value()).ToObject(), nil 139 } 140 141 func intInvert(f *Frame, o *Object) (*Object, *BaseException) { 142 return NewInt(^toIntUnsafe(o).Value()).ToObject(), nil 143 } 144 145 func intLE(f *Frame, v, w *Object) (*Object, *BaseException) { 146 return intCompare(compareOpLE, toIntUnsafe(v), w), nil 147 } 148 149 func intLong(f *Frame, o *Object) (*Object, *BaseException) { 150 return NewLong(big.NewInt(int64(toIntUnsafe(o).Value()))).ToObject(), nil 151 } 152 153 func intLShift(f *Frame, v, w *Object) (*Object, *BaseException) { 154 return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return v, w, false }) 155 } 156 157 func intLT(f *Frame, v, w *Object) (*Object, *BaseException) { 158 return intCompare(compareOpLT, toIntUnsafe(v), w), nil 159 } 160 161 func intMod(f *Frame, v, w *Object) (*Object, *BaseException) { 162 return intDivModOp(f, "__mod__", v, w, intCheckedMod, longMod) 163 } 164 165 func intMul(f *Frame, v, w *Object) (*Object, *BaseException) { 166 return intAddMulOp(f, "__mul__", v, w, intCheckedMul, longMul) 167 } 168 169 func intNative(f *Frame, o *Object) (reflect.Value, *BaseException) { 170 return reflect.ValueOf(toIntUnsafe(o).Value()), nil 171 } 172 173 func intNE(f *Frame, v, w *Object) (*Object, *BaseException) { 174 return intCompare(compareOpNE, toIntUnsafe(v), w), nil 175 } 176 177 func intNeg(f *Frame, o *Object) (*Object, *BaseException) { 178 z := toIntUnsafe(o) 179 if z.Value() == MinInt { 180 nz := big.NewInt(int64(z.Value())) 181 return NewLong(nz.Neg(nz)).ToObject(), nil 182 } 183 return NewInt(-z.Value()).ToObject(), nil 184 } 185 186 func intNew(f *Frame, t *Type, args Args, _ KWArgs) (*Object, *BaseException) { 187 if len(args) == 0 { 188 return newObject(t), nil 189 } 190 o := args[0] 191 if len(args) == 1 && o.typ.slots.Int != nil { 192 i, raised := ToInt(f, o) 193 if raised != nil { 194 return nil, raised 195 } 196 if t == IntType { 197 return i, nil 198 } 199 n := 0 200 if i.isInstance(LongType) { 201 n, raised = toLongUnsafe(i).IntValue(f) 202 if raised != nil { 203 return nil, raised 204 } 205 } else { 206 n = toIntUnsafe(i).Value() 207 } 208 ret := newObject(t) 209 toIntUnsafe(ret).value = n 210 return ret, nil 211 } 212 if len(args) > 2 { 213 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("int() takes at most 2 arguments (%d given)", len(args))) 214 } 215 if !o.isInstance(StrType) { 216 if len(args) == 2 { 217 return nil, f.RaiseType(TypeErrorType, "int() can't convert non-string with explicit base") 218 } 219 return nil, f.RaiseType(TypeErrorType, fmt.Sprintf("int() argument must be a string or a number, not '%s'", o.typ.Name())) 220 } 221 s := toStrUnsafe(o).Value() 222 base := 10 223 if len(args) == 2 { 224 var raised *BaseException 225 base, raised = ToIntValue(f, args[1]) 226 if raised != nil { 227 return nil, raised 228 } 229 if base < 0 || base == 1 || base > 36 { 230 return nil, f.RaiseType(ValueErrorType, "int() base must be >= 2 and <= 36") 231 } 232 } 233 i, ok := numParseInteger(new(big.Int), s, base) 234 if !ok { 235 format := "invalid literal for int() with base %d: %s" 236 return nil, f.RaiseType(ValueErrorType, fmt.Sprintf(format, base, s)) 237 } 238 if !numInIntRange(i) { 239 if t == IntType { 240 return NewLong(i).ToObject(), nil 241 } 242 return nil, f.RaiseType(OverflowErrorType, "Python int too large to convert to a Go int") 243 } 244 if t != IntType { 245 o := newObject(t) 246 toIntUnsafe(o).value = int(i.Int64()) 247 return o, nil 248 } 249 return NewInt(int(i.Int64())).ToObject(), nil 250 } 251 252 func intNonZero(f *Frame, o *Object) (*Object, *BaseException) { 253 return GetBool(toIntUnsafe(o).Value() != 0).ToObject(), nil 254 } 255 256 func intOct(f *Frame, o *Object) (*Object, *BaseException) { 257 val := numberToBase("0", 8, o) 258 if val == "00" { 259 val = "0" 260 } 261 return NewStr(val).ToObject(), nil 262 } 263 264 func intOr(f *Frame, v, w *Object) (*Object, *BaseException) { 265 if !w.isInstance(IntType) { 266 return NotImplemented, nil 267 } 268 return NewInt(toIntUnsafe(v).Value() | toIntUnsafe(w).Value()).ToObject(), nil 269 } 270 271 func intPos(f *Frame, o *Object) (*Object, *BaseException) { 272 return o, nil 273 } 274 275 func intPow(f *Frame, v, w *Object) (*Object, *BaseException) { 276 if w.isInstance(IntType) { 277 // First try to use the faster floating point arithmetic 278 // on the CPU, then falls back to slower methods. 279 // IEEE float64 has 52bit of precision, so the result should be 280 // less than MaxInt32 to be representable as an exact integer. 281 // This assumes that int is at least 32bit. 282 vInt := toIntUnsafe(v).Value() 283 wInt := toIntUnsafe(w).Value() 284 if 0 < vInt && vInt <= math.MaxInt32 && 0 < wInt && wInt <= math.MaxInt32 { 285 res := math.Pow(float64(vInt), float64(wInt)) 286 // Can the result be interpreted as an int? 287 if !math.IsNaN(res) && !math.IsInf(res, 0) && res <= math.MaxInt32 { 288 return NewInt(int(res)).ToObject(), nil 289 } 290 } 291 // Special cases. 292 if vInt == 0 { 293 if wInt < 0 { 294 return nil, f.RaiseType(ZeroDivisionErrorType, "0.0 cannot be raised to a negative power") 295 } 296 if wInt == 0 { 297 return NewInt(1).ToObject(), nil 298 } 299 return NewInt(0).ToObject(), nil 300 } 301 // If w < 0, the result must be a floating point number. 302 // We convert both arguments to float and continue. 303 if wInt < 0 { 304 return floatPow(f, NewFloat(float64(vInt)).ToObject(), NewFloat(float64(wInt)).ToObject()) 305 } 306 // Else we convert to Long and continue there. 307 return longPow(f, NewLong(big.NewInt(int64(vInt))).ToObject(), NewLong(big.NewInt(int64(wInt))).ToObject()) 308 } 309 return NotImplemented, nil 310 } 311 312 func intRAdd(f *Frame, v, w *Object) (*Object, *BaseException) { 313 return intAddMulOp(f, "__radd__", v, w, intCheckedAdd, longAdd) 314 } 315 316 func intRDiv(f *Frame, v, w *Object) (*Object, *BaseException) { 317 return intDivModOp(f, "__rdiv__", v, w, func(v, w int) (int, divModResult) { 318 return intCheckedDiv(w, v) 319 }, func(z, x, y *big.Int) { 320 longDiv(z, y, x) 321 }) 322 } 323 324 func intRDivMod(f *Frame, v, w *Object) (*Object, *BaseException) { 325 return intDivAndModOp(f, "__rdivmod__", v, w, func(v, w int) (int, int, divModResult) { 326 return intCheckedDivMod(w, v) 327 }, func(z, m, x, y *big.Int) { 328 longDivAndMod(z, m, y, x) 329 }) 330 } 331 332 func intRepr(f *Frame, o *Object) (*Object, *BaseException) { 333 return NewStr(strconv.FormatInt(int64(toIntUnsafe(o).Value()), 10)).ToObject(), nil 334 } 335 336 func intRMod(f *Frame, v, w *Object) (*Object, *BaseException) { 337 return intDivModOp(f, "__rmod__", v, w, func(v, w int) (int, divModResult) { 338 return intCheckedMod(w, v) 339 }, func(z, x, y *big.Int) { 340 longMod(z, y, x) 341 }) 342 } 343 344 func intRMul(f *Frame, v, w *Object) (*Object, *BaseException) { 345 return intAddMulOp(f, "__rmul__", v, w, intCheckedMul, longMul) 346 } 347 348 func intRLShift(f *Frame, v, w *Object) (*Object, *BaseException) { 349 return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return w, v, false }) 350 } 351 352 func intRRShift(f *Frame, v, w *Object) (*Object, *BaseException) { 353 return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return w, v, true }) 354 } 355 356 func intRShift(f *Frame, v, w *Object) (*Object, *BaseException) { 357 return intShiftOp(f, v, w, func(v, w int) (int, int, bool) { return v, w, true }) 358 } 359 360 func intRSub(f *Frame, v, w *Object) (*Object, *BaseException) { 361 return intAddMulOp(f, "__rsub__", v, w, func(v, w int) (int, bool) { 362 return intCheckedSub(w, v) 363 }, func(z, x, y *big.Int) { 364 longSub(z, y, x) 365 }) 366 } 367 368 func intSub(f *Frame, v, w *Object) (*Object, *BaseException) { 369 return intAddMulOp(f, "__sub__", v, w, intCheckedSub, longSub) 370 } 371 372 func intXor(f *Frame, v, w *Object) (*Object, *BaseException) { 373 if !w.isInstance(IntType) { 374 return NotImplemented, nil 375 } 376 return NewInt(toIntUnsafe(v).Value() ^ toIntUnsafe(w).Value()).ToObject(), nil 377 } 378 379 func initIntType(dict map[string]*Object) { 380 dict["__getnewargs__"] = newBuiltinFunction("__getnewargs__", intGetNewArgs).ToObject() 381 IntType.slots.Abs = &unaryOpSlot{intAbs} 382 IntType.slots.Add = &binaryOpSlot{intAdd} 383 IntType.slots.And = &binaryOpSlot{intAnd} 384 IntType.slots.Div = &binaryOpSlot{intDiv} 385 IntType.slots.DivMod = &binaryOpSlot{intDivMod} 386 IntType.slots.Eq = &binaryOpSlot{intEq} 387 IntType.slots.FloorDiv = &binaryOpSlot{intDiv} 388 IntType.slots.GE = &binaryOpSlot{intGE} 389 IntType.slots.GT = &binaryOpSlot{intGT} 390 IntType.slots.Float = &unaryOpSlot{intFloat} 391 IntType.slots.Hash = &unaryOpSlot{intHash} 392 IntType.slots.Hex = &unaryOpSlot{intHex} 393 IntType.slots.Index = &unaryOpSlot{intIndex} 394 IntType.slots.Int = &unaryOpSlot{intInt} 395 IntType.slots.Invert = &unaryOpSlot{intInvert} 396 IntType.slots.LE = &binaryOpSlot{intLE} 397 IntType.slots.LShift = &binaryOpSlot{intLShift} 398 IntType.slots.LT = &binaryOpSlot{intLT} 399 IntType.slots.Long = &unaryOpSlot{intLong} 400 IntType.slots.Mod = &binaryOpSlot{intMod} 401 IntType.slots.Mul = &binaryOpSlot{intMul} 402 IntType.slots.Native = &nativeSlot{intNative} 403 IntType.slots.NE = &binaryOpSlot{intNE} 404 IntType.slots.Neg = &unaryOpSlot{intNeg} 405 IntType.slots.New = &newSlot{intNew} 406 IntType.slots.NonZero = &unaryOpSlot{intNonZero} 407 IntType.slots.Oct = &unaryOpSlot{intOct} 408 IntType.slots.Or = &binaryOpSlot{intOr} 409 IntType.slots.Pos = &unaryOpSlot{intPos} 410 IntType.slots.Pow = &binaryOpSlot{intPow} 411 IntType.slots.RAdd = &binaryOpSlot{intRAdd} 412 IntType.slots.RAnd = &binaryOpSlot{intAnd} 413 IntType.slots.RDiv = &binaryOpSlot{intRDiv} 414 IntType.slots.RDivMod = &binaryOpSlot{intRDivMod} 415 IntType.slots.Repr = &unaryOpSlot{intRepr} 416 IntType.slots.RFloorDiv = &binaryOpSlot{intRDiv} 417 IntType.slots.RMod = &binaryOpSlot{intRMod} 418 IntType.slots.RMul = &binaryOpSlot{intRMul} 419 IntType.slots.ROr = &binaryOpSlot{intOr} 420 IntType.slots.RLShift = &binaryOpSlot{intRLShift} 421 IntType.slots.RRShift = &binaryOpSlot{intRRShift} 422 IntType.slots.RShift = &binaryOpSlot{intRShift} 423 IntType.slots.RSub = &binaryOpSlot{intRSub} 424 IntType.slots.RXor = &binaryOpSlot{intXor} 425 IntType.slots.Sub = &binaryOpSlot{intSub} 426 IntType.slots.Xor = &binaryOpSlot{intXor} 427 } 428 429 type divModResult int 430 431 const ( 432 divModOK divModResult = iota 433 divModOverflow = iota 434 divModZeroDivision = iota 435 ) 436 437 func intCompare(op compareOp, v *Int, w *Object) *Object { 438 if !w.isInstance(IntType) { 439 return NotImplemented 440 } 441 lhs, rhs := v.Value(), toIntUnsafe(w).Value() 442 result := false 443 switch op { 444 case compareOpLT: 445 result = lhs < rhs 446 case compareOpLE: 447 result = lhs <= rhs 448 case compareOpEq: 449 result = lhs == rhs 450 case compareOpNE: 451 result = lhs != rhs 452 case compareOpGE: 453 result = lhs >= rhs 454 case compareOpGT: 455 result = lhs > rhs 456 } 457 return GetBool(result).ToObject() 458 } 459 460 func intAddMulOp(f *Frame, method string, v, w *Object, fun func(v, w int) (int, bool), bigFun func(z, x, y *big.Int)) (*Object, *BaseException) { 461 if !w.isInstance(IntType) { 462 return NotImplemented, nil 463 } 464 r, ok := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value()) 465 if !ok { 466 return longCallBinary(bigFun, intToLong(toIntUnsafe(v)), intToLong(toIntUnsafe(w))), nil 467 } 468 return NewInt(r).ToObject(), nil 469 } 470 471 func intCheckedDiv(v, w int) (int, divModResult) { 472 q, _, r := intCheckedDivMod(v, w) 473 return q, r 474 } 475 476 func intCheckedDivMod(v, w int) (int, int, divModResult) { 477 if w == 0 { 478 return 0, 0, divModZeroDivision 479 } 480 if v == MinInt && w == -1 { 481 return 0, 0, divModOverflow 482 } 483 q := v / w 484 m := v % w 485 if m != 0 && (w^m) < 0 { 486 // In Python the result of the modulo operator is always the 487 // same sign as the divisor, whereas in Go, the result is 488 // always the same sign as the dividend. Therefore we need to 489 // do an adjustment when the sign of the modulo result differs 490 // from that of the divisor. 491 m += w 492 // Relatedly, in Python the result of division truncates toward 493 // negative infinity whereas it truncates toward zero in Go. 494 // The fact that the signs of the divisor and the modulo result 495 // differ implies that the quotient is also negative so we also 496 // adjust the quotient here. 497 q-- 498 } 499 return q, m, divModOK 500 } 501 502 func intCheckedAdd(v, w int) (int, bool) { 503 if (v > 0 && w > MaxInt-v) || (v < 0 && w < MinInt-v) { 504 return 0, false 505 } 506 return v + w, true 507 } 508 509 func intCheckedMod(v, w int) (int, divModResult) { 510 _, m, r := intCheckedDivMod(v, w) 511 return m, r 512 } 513 514 func intCheckedMul(v, w int) (int, bool) { 515 if v == 0 || w == 0 || v == 1 || w == 1 { 516 return v * w, true 517 } 518 // Since MinInt can only be multiplied by zero and one safely and we've 519 // already handled that case above, we know this multiplication will 520 // overflow. Unfortunately the division check below will fail to catch 521 // this by coincidence: MinInt * -1 overflows to MinInt, causing the 522 // expression x/w to overflow, coincidentally producing MinInt which 523 // makes it seem as though the multiplication was correct. 524 if v == MinInt || w == MinInt { 525 return 0, false 526 } 527 x := v * w 528 if x/w != v { 529 return 0, false 530 } 531 return x, true 532 } 533 534 func intCheckedSub(v, w int) (int, bool) { 535 if (w > 0 && v < MinInt+w) || (w < 0 && v > MaxInt+w) { 536 return 0, false 537 } 538 return v - w, true 539 } 540 541 func intDivModOp(f *Frame, method string, v, w *Object, fun func(v, w int) (int, divModResult), bigFun func(z, x, y *big.Int)) (*Object, *BaseException) { 542 if !w.isInstance(IntType) { 543 return NotImplemented, nil 544 } 545 x, r := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value()) 546 switch r { 547 case divModOverflow: 548 return longCallBinary(bigFun, intToLong(toIntUnsafe(v)), intToLong(toIntUnsafe(w))), nil 549 case divModZeroDivision: 550 return nil, f.RaiseType(ZeroDivisionErrorType, "integer division or modulo by zero") 551 } 552 return NewInt(x).ToObject(), nil 553 } 554 555 func intDivAndModOp(f *Frame, method string, v, w *Object, fun func(v, w int) (int, int, divModResult), bigFun func(z, m, x, y *big.Int)) (*Object, *BaseException) { 556 if !w.isInstance(IntType) { 557 return NotImplemented, nil 558 } 559 q, m, r := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value()) 560 switch r { 561 case divModOverflow: 562 return longCallBinaryTuple(bigFun, intToLong(toIntUnsafe(v)), intToLong(toIntUnsafe(w))), nil 563 case divModZeroDivision: 564 return nil, f.RaiseType(ZeroDivisionErrorType, "integer division or modulo by zero") 565 } 566 return NewTuple2(NewInt(q).ToObject(), NewInt(m).ToObject()).ToObject(), nil 567 } 568 569 func intShiftOp(f *Frame, v, w *Object, fun func(int, int) (int, int, bool)) (*Object, *BaseException) { 570 if !w.isInstance(IntType) { 571 return NotImplemented, nil 572 } 573 lhs, rhs, rshift := fun(toIntUnsafe(v).Value(), toIntUnsafe(w).Value()) 574 if rhs < 0 { 575 return nil, f.RaiseType(ValueErrorType, "negative shift count") 576 } 577 var result int 578 n := uint(rhs) 579 if rshift { 580 result = lhs >> n 581 } else { 582 result = lhs << n 583 if result>>n != lhs { 584 return NewLong(new(big.Int).Lsh(big.NewInt(int64(lhs)), n)).ToObject(), nil 585 } 586 } 587 return NewInt(result).ToObject(), nil 588 } 589 590 func intToLong(o *Int) *Long { 591 return NewLong(big.NewInt(int64(o.Value()))) 592 } 593 594 func makeInternedInts() [internedIntMax - internedIntMin + 1]Int { 595 var ints [internedIntMax - internedIntMin + 1]Int 596 for i := internedIntMin; i <= internedIntMax; i++ { 597 ints[i-internedIntMin] = Int{Object{typ: IntType}, i} 598 } 599 return ints 600 }