Commit 5cfcc4e6 authored by Boxiang Sun's avatar Boxiang Sun

add missing int attributes compared with CPython

parent f1e9b55f
......@@ -378,6 +378,16 @@ extern "C" i64 mod_i64_i64(i64 lhs, i64 rhs) {
}
extern "C" Box* pow_i64_i64(i64 lhs, i64 rhs, Box* mod) {
if (mod != None) {
if (!PyInt_Check(mod)) {
return NotImplemented;
}
BoxedInt* mod_int = static_cast<BoxedInt*>(mod);
if (mod_int->n == 0) {
raiseExcHelper(ValueError, "pow() 3rd argument cannot be 0");
}
}
i64 orig_rhs = rhs;
i64 rtn = 1, curpow = lhs;
......@@ -424,6 +434,19 @@ extern "C" Box* intAdd(BoxedInt* lhs, Box* rhs) {
}
}
Box* intRAdd(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__radd__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return add_i64_i64(lhs->n, rhs_int->n);
} else {
return NotImplemented;
}
}
extern "C" Box* intAndInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -441,6 +464,18 @@ extern "C" Box* intAnd(BoxedInt* lhs, Box* rhs) {
return boxInt(lhs->n & rhs_int->n);
}
Box* intRAnd(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rand__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(lhs->n & rhs_int->n);
}
extern "C" Box* intOrInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -458,6 +493,17 @@ extern "C" Box* intOr(BoxedInt* lhs, Box* rhs) {
return boxInt(lhs->n | rhs_int->n);
}
Box* intROr(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__ror__' requires a 'int' object but received a '%s'", getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(lhs->n | rhs_int->n);
}
extern "C" Box* intXorInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -475,6 +521,18 @@ extern "C" Box* intXor(BoxedInt* lhs, Box* rhs) {
return boxInt(lhs->n ^ rhs_int->n);
}
Box* intRXor(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rxor__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(lhs->n ^ rhs_int->n);
}
extern "C" Box* intDivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -504,6 +562,18 @@ extern "C" Box* intDiv(BoxedInt* lhs, Box* rhs) {
}
}
Box* intRDiv(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rdiv__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
return div_i64_i64(static_cast<BoxedInt*>(rhs)->n, lhs->n);
} else {
return NotImplemented;
}
}
extern "C" Box* intFloordivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -534,6 +604,18 @@ extern "C" Box* intFloordiv(BoxedInt* lhs, Box* rhs) {
}
}
Box* intRFloordiv(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rfloordiv__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
return div_i64_i64(static_cast<BoxedInt*>(rhs)->n, lhs->n);
}
extern "C" Box* intTruedivInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -568,6 +650,18 @@ extern "C" Box* intTruediv(BoxedInt* lhs, Box* rhs) {
}
}
Box* intRTruediv(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rtruediv__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
return intTruedivInt(static_cast<BoxedInt*>(rhs), lhs);
} else {
return NotImplemented;
}
}
extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -581,7 +675,7 @@ extern "C" Box* intLShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
if ((res >> rhs->n) == lhs->n)
return boxInt(lhs->n << rhs->n);
}
return longLshift(boxLong(lhs->n), rhs);
return longLShiftLong(boxLong(lhs->n), rhs);
}
extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
......@@ -590,7 +684,7 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
getTypeName(lhs));
if (rhs->cls == long_cls)
return longLshift(boxLong(lhs->n), rhs);
return longLShiftLong(boxLong(lhs->n), rhs);
if (!PyInt_Check(rhs)) {
return NotImplemented;
......@@ -599,6 +693,19 @@ extern "C" Box* intLShift(BoxedInt* lhs, Box* rhs) {
return intLShiftInt(lhs, rhs_int);
}
Box* intRLShift(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rlshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intLShiftInt(rhs_int, lhs);
}
extern "C" Box* intModInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -616,6 +723,18 @@ extern "C" Box* intMod(BoxedInt* lhs, Box* rhs) {
return boxInt(mod_i64_i64(lhs->n, rhs_int->n));
}
Box* intRMod(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rmod__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return boxInt(mod_i64_i64(rhs_int->n, lhs->n));
}
extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__divmod__' requires a 'int' object but received a '%s'",
......@@ -637,6 +756,16 @@ extern "C" Box* intDivmod(BoxedInt* lhs, Box* rhs) {
return createTuple(2, arg);
}
Box* intRDivmod(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rdivmod__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
return intDivmod(static_cast<BoxedInt*>(rhs), lhs);
}
extern "C" Box* intMulInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
......@@ -665,6 +794,17 @@ extern "C" Box* intMul(BoxedInt* lhs, Box* rhs) {
}
}
Box* intRMul(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rmul__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs))
return NotImplemented;
return intMul(lhs, rhs);
}
static void _addFuncPow(const char* name, ConcreteCompilerType* rtn_type, void* float_func, void* int_func) {
std::vector<ConcreteCompilerType*> v_ifu{ BOXED_INT, BOXED_FLOAT, UNKNOWN };
std::vector<ConcreteCompilerType*> v_uuu{ UNKNOWN, UNKNOWN, UNKNOWN };
......@@ -704,17 +844,10 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) {
return NotImplemented;
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
BoxedInt* mod_int = static_cast<BoxedInt*>(mod);
if (mod != None) {
if (rhs_int->n < 0)
raiseExcHelper(TypeError, "pow() 2nd argument "
"cannot be negative when 3rd argument specified");
if (!PyInt_Check(mod)) {
return NotImplemented;
} else if (mod_int->n == 0) {
raiseExcHelper(ValueError, "pow() 3rd argument cannot be 0");
}
}
Box* rtn = pow_i64_i64(lhs->n, rhs_int->n, mod);
......@@ -723,8 +856,29 @@ extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) {
return rtn;
}
extern "C" Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
Box* intRPow(BoxedInt* lhs, Box* rhs, Box* mod) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rpow__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs))
return NotImplemented;
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
if (mod != None) {
if (lhs->n < 0)
raiseExcHelper(TypeError, "pow() 2nd argument "
"cannot be negative when 3rd argument specified");
}
Box* rtn = pow_i64_i64(rhs_int->n, lhs->n, mod);
if (PyLong_Check(rtn))
return longInt(rtn);
return rtn;
}
Box* intRShiftInt(BoxedInt* lhs, BoxedInt* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
assert(PyInt_Check(rhs));
if (rhs->n < 0)
......@@ -739,7 +893,7 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
getTypeName(lhs));
if (rhs->cls == long_cls)
return longRshift(boxLong(lhs->n), rhs);
return longRShiftLong(boxLong(lhs->n), rhs);
if (!PyInt_Check(rhs)) {
return NotImplemented;
......@@ -748,6 +902,18 @@ extern "C" Box* intRShift(BoxedInt* lhs, Box* rhs) {
return intRShiftInt(lhs, rhs_int);
}
Box* intRRShift(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rrshift__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intRShiftInt(rhs_int, lhs);
}
extern "C" Box* intSubInt(BoxedInt* lhs, BoxedInt* rhs) {
assert(PyInt_Check(lhs));
assert(PyInt_Check(rhs));
......@@ -775,6 +941,19 @@ extern "C" Box* intSub(BoxedInt* lhs, Box* rhs) {
}
}
Box* intRSub(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__rsub__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (PyInt_Check(rhs)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return sub_i64_i64(rhs_int->n, lhs->n);
} else {
return NotImplemented;
}
}
extern "C" Box* intInvert(BoxedInt* v) {
if (!PyInt_Check(v))
raiseExcHelper(TypeError, "descriptor '__invert__' requires a 'int' object but received a '%s'",
......@@ -836,6 +1015,16 @@ extern "C" Box* intHash(BoxedInt* self) {
return boxInt(self->n);
}
Box* intAbs(BoxedInt* v) {
if (!PyInt_Check(v))
raiseExcHelper(TypeError, "descriptor '__abs__' requires a 'int' object but received a '%s'", getTypeName(v));
if (v->n == PYSTON_INT_MIN) {
return longNeg(boxLong(v->n));
}
return boxInt(std::abs(v->n));
}
extern "C" Box* intBin(BoxedInt* self) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__bin__' requires a 'int' object but received a '%s'",
......@@ -844,6 +1033,20 @@ extern "C" Box* intBin(BoxedInt* self) {
return _PyInt_Format(reinterpret_cast<PyIntObject*>(self), 2, 0);
}
Box* intCoerce(BoxedInt* lhs, Box* rhs) {
if (!PyInt_Check(lhs))
raiseExcHelper(TypeError, "descriptor '__coerce__' requires a 'int' object but received a '%s'",
getTypeName(lhs));
if (!PyInt_Check(rhs)) {
return NotImplemented;
}
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return BoxedTuple::create({ lhs, rhs_int });
}
extern "C" Box* intHex(BoxedInt* self) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__hex__' requires a 'int' object but received a '%s'",
......@@ -902,6 +1105,14 @@ Box* intFloat(BoxedInt* self) {
return boxFloat(self->n);
}
Box* intLong(BoxedInt* self) {
if (!PyInt_Check(self))
raiseExcHelper(TypeError, "descriptor '__long__' requires a 'int' object but received a '%s'",
getTypeName(self));
return boxLong(self->n);
}
extern "C" Box* intIndex(BoxedInt* v) {
if (PyInt_CheckExact(v))
return v;
......@@ -1167,6 +1378,23 @@ void setupInt() {
_addFuncIntFloatUnknown("__mul__", (void*)intMulInt, (void*)intMulFloat, (void*)intMul);
_addFuncIntUnknown("__mod__", BOXED_INT, (void*)intModInt, (void*)intMod);
_addFuncPow("__pow__", BOXED_INT, (void*)intPowFloat, (void*)intPow);
int_cls->giveAttr("__radd__", new BoxedFunction(FunctionMetadata::create((void*)intRAdd, UNKNOWN, 2)));
int_cls->giveAttr("__rand__", new BoxedFunction(FunctionMetadata::create((void*)intRAnd, UNKNOWN, 2)));
int_cls->giveAttr("__ror__", new BoxedFunction(FunctionMetadata::create((void*)intROr, UNKNOWN, 2)));
int_cls->giveAttr("__rxor__", new BoxedFunction(FunctionMetadata::create((void*)intRXor, UNKNOWN, 2)));
int_cls->giveAttr("__rsub__", new BoxedFunction(FunctionMetadata::create((void*)intRSub, UNKNOWN, 2)));
int_cls->giveAttr("__rmul__", new BoxedFunction(FunctionMetadata::create((void*)intRMul, UNKNOWN, 2)));
int_cls->giveAttr("__rdiv__", new BoxedFunction(FunctionMetadata::create((void*)intRDiv, UNKNOWN, 2)));
int_cls->giveAttr("__rfloordiv__", new BoxedFunction(FunctionMetadata::create((void*)intRFloordiv, UNKNOWN, 2)));
int_cls->giveAttr("__rtruediv__", new BoxedFunction(FunctionMetadata::create((void*)intRTruediv, UNKNOWN, 2)));
int_cls->giveAttr("__rmod__", new BoxedFunction(FunctionMetadata::create((void*)intRMod, UNKNOWN, 2)));
int_cls->giveAttr("__rdivmod__", new BoxedFunction(FunctionMetadata::create((void*)intRDivmod, UNKNOWN, 2)));
int_cls->giveAttr("__rpow__",
new BoxedFunction(FunctionMetadata::create((void*)intRPow, UNKNOWN, 3, false, false), { None }));
int_cls->giveAttr("__rrshift__", new BoxedFunction(FunctionMetadata::create((void*)intRRShift, UNKNOWN, 2)));
int_cls->giveAttr("__rlshift__", new BoxedFunction(FunctionMetadata::create((void*)intRLShift, UNKNOWN, 2)));
// Note: CPython implements int comparisons using tp_compare
int_cls->tp_richcompare = int_richcompare;
......@@ -1181,6 +1409,9 @@ void setupInt() {
int_cls->tp_hash = (hashfunc)int_hash;
int_cls->giveAttr("__divmod__", new BoxedFunction(FunctionMetadata::create((void*)intDivmod, UNKNOWN, 2)));
int_cls->giveAttr("__coerce__", new BoxedFunction(FunctionMetadata::create((void*)intCoerce, UNKNOWN, 2)));
int_cls->giveAttr("__abs__", new BoxedFunction(FunctionMetadata::create((void*)intAbs, UNKNOWN, 1)));
int_cls->giveAttr("__bin__", new BoxedFunction(FunctionMetadata::create((void*)intBin, STR, 1)));
int_cls->giveAttr("__hex__", new BoxedFunction(FunctionMetadata::create((void*)intHex, STR, 1)));
int_cls->giveAttr("__oct__", new BoxedFunction(FunctionMetadata::create((void*)intOct, STR, 1)));
......@@ -1189,6 +1420,23 @@ void setupInt() {
int_cls->giveAttr("__index__", new BoxedFunction(FunctionMetadata::create((void*)intIndex, BOXED_INT, 1)));
int_cls->giveAttr("__int__", new BoxedFunction(FunctionMetadata::create((void*)intInt, BOXED_INT, 1)));
int_cls->giveAttr("__float__", new BoxedFunction(FunctionMetadata::create((void*)intFloat, BOXED_FLOAT, 1)));
int_cls->giveAttr("__long__", new BoxedFunction(FunctionMetadata::create((void*)intLong, LONG, 1)));
int_cls->giveAttr("__doc__",
boxString("int(x=0) -> int or long\n"
"int(x, base=10) -> int or long\n"
"\n"
"Convert a number or string to an integer, or return 0 if no arguments\n"
"are given. If x is floating point, the conversion truncates towards zero.\n"
"If x is outside the integer range, the function returns a long instead.\n"
"\n"
"If x is not a number or if base is given, then x must be a string or\n"
"Unicode object representing an integer literal in the given base. The\n"
"literal can be preceded by '+' or '-' and be surrounded by whitespace.\n"
"The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to\n"
"interpret the base from the string as an integer literal.\n"
">>> int('0b100', base=0)\n"
"4"));
auto int_new = FunctionMetadata::create((void*)intNew<CXX>, UNKNOWN, 3, false, false,
ParamNames({ "", "x", "base" }, "", ""), CXX);
......
......@@ -178,3 +178,53 @@ if sys.version_info >= (2, 7, 6):
print(e.message)
else:
print("int() missing string argument")
pow_test_data = [42, 3, 3L, 4.5, "x", 0, -42, None]
for rhs in pow_test_data:
for lhs in pow_test_data:
for mod in pow_test_data:
try:
print(int.__rpow__(rhs, lhs, mod))
except Exception as e:
print(e.message)
unary_test_data = [-42, -0, 0, 42, max_int, min_int]
for i in unary_test_data:
print(int.__abs__(i))
print(int.__long__(i))
print(int.__float__(i))
data = ["-1", "0", "1",
"5", "-5",
"5.0", "5L", "0L", "5+5j", "0.0",
"\"5\"", "None",
]
operations = ["__radd__",
"__rand__",
"__ror__",
"__rxor__",
"__rsub__",
"__rmul__",
"__rdiv__",
"__rfloordiv__",
"__rpow__",
"__rmod__",
"__rdivmod__",
"__rtruediv__",
"__rrshift__",
"__rlshift__",
"__coerce__",
]
for x in data:
for y in data:
for operation in operations:
try:
print(eval("int.{op}({arg1}, {arg2})".format(op=operation,
arg1=x,
arg2=y)))
except Exception as e:
print(e.message)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment