Commit 065ac619 authored by Boxiang Sun's avatar Boxiang Sun

add missing int attributes compared with CPython

parent bd361100
......@@ -424,6 +424,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 +454,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 +483,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 +511,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 +552,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 +594,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 +640,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 +665,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 +674,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 +683,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 +713,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 +746,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 +784,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 };
......@@ -723,8 +853,25 @@ 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) {
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);
Box* rtn = pow_i64_i64(rhs_int->n, lhs->n, None);
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 +886,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 +895,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 +934,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 +1008,13 @@ 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));
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 +1023,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 +1095,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;
......@@ -1157,6 +1358,7 @@ void setupInt() {
ParamNames::empty(), CAPI)));
_addFuncIntFloatUnknown("__add__", (void*)intAddInt, (void*)intAddFloat, (void*)intAdd);
int_cls->giveAttr("__radd__", new BoxedFunction(FunctionMetadata::create((void*)intRAdd, UNKNOWN, 2)));
_addFuncIntUnknown("__and__", BOXED_INT, (void*)intAndInt, (void*)intAnd);
_addFuncIntUnknown("__or__", BOXED_INT, (void*)intOrInt, (void*)intOr);
_addFuncIntUnknown("__xor__", BOXED_INT, (void*)intXorInt, (void*)intXor);
......@@ -1167,6 +1369,21 @@ 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("__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, 2)));
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 +1398,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, BOXED_INT, 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 +1409,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, UNKNOWN, 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,42 @@ if sys.version_info >= (2, 7, 6):
print(e.message)
else:
print("int() missing string argument")
unary_test_data = [-42, -0, 0, 42]
for i in unary_test_data:
print(int.__abs__(i))
print(int.__long__(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