Commit 9956a566 authored by Marius Wachtler's avatar Marius Wachtler

Add pow(), long.__mod__, __index__, slice and xrange long arg support,

support for 3arg pow, long("0xBB", 16) and long("0xBBL", 0)
parent 56495410
......@@ -1038,6 +1038,149 @@ static PyObject* binary_op(PyObject* v, PyObject* w, const int op_slot, const ch
return result;
}
/*
Calling scheme used for ternary operations:
*** In some cases, w.op is called before v.op; see binary_op1. ***
v w z Action
-------------------------------------------------------------------
new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
old old old coerce(v,w,z), v.op(v,w,z)
Legend:
-------
* new == new style number
* old == old style number
* Action indicates the order in which operations are tried until either
a valid result is produced or an error occurs.
* coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
only if z != Py_None; if z == Py_None, then it is treated as absent
variable and only coerce(v,w) is tried.
*/
static PyObject* ternary_op(PyObject* v, PyObject* w, PyObject* z, const int op_slot, const char* op_name) noexcept {
PyNumberMethods* mv, *mw, *mz;
PyObject* x = NULL;
ternaryfunc slotv = NULL;
ternaryfunc slotw = NULL;
ternaryfunc slotz = NULL;
mv = v->cls->tp_as_number;
mw = w->cls->tp_as_number;
if (mv != NULL && NEW_STYLE_NUMBER(v))
slotv = NB_TERNOP(mv, op_slot);
if (w->cls != v->cls && mw != NULL && NEW_STYLE_NUMBER(w)) {
slotw = NB_TERNOP(mw, op_slot);
if (slotw == slotv)
slotw = NULL;
}
if (slotv) {
if (slotw && PyType_IsSubtype(w->cls, v->cls)) {
x = slotw(v, w, z);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
slotw = NULL;
}
x = slotv(v, w, z);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
}
if (slotw) {
x = slotw(v, w, z);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
}
mz = z->cls->tp_as_number;
if (mz != NULL && NEW_STYLE_NUMBER(z)) {
slotz = NB_TERNOP(mz, op_slot);
if (slotz == slotv || slotz == slotw)
slotz = NULL;
if (slotz) {
x = slotz(v, w, z);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
}
}
if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w) || (z != Py_None && !NEW_STYLE_NUMBER(z))) {
/* we have an old style operand, coerce */
PyObject* v1, *z1, *w2, *z2;
int c;
c = PyNumber_Coerce(&v, &w);
if (c != 0)
goto error3;
/* Special case: if the third argument is None, it is
treated as absent argument and not coerced. */
if (z == Py_None) {
if (v->cls->tp_as_number) {
slotz = NB_TERNOP(v->cls->tp_as_number, op_slot);
if (slotz)
x = slotz(v, w, z);
else
c = -1;
} else
c = -1;
goto error2;
}
v1 = v;
z1 = z;
c = PyNumber_Coerce(&v1, &z1);
if (c != 0)
goto error2;
w2 = w;
z2 = z1;
c = PyNumber_Coerce(&w2, &z2);
if (c != 0)
goto error1;
if (v1->cls->tp_as_number != NULL) {
slotv = NB_TERNOP(v1->cls->tp_as_number, op_slot);
if (slotv)
x = slotv(v1, w2, z2);
else
c = -1;
} else
c = -1;
Py_DECREF(w2);
Py_DECREF(z2);
error1:
Py_DECREF(v1);
Py_DECREF(z1);
error2:
Py_DECREF(v);
Py_DECREF(w);
error3:
if (c >= 0)
return x;
}
if (z == Py_None)
PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for ** or pow(): "
"'%.100s' and '%.100s'",
v->cls->tp_name, w->cls->tp_name);
else
PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for pow(): "
"'%.100s', '%.100s', '%.100s'",
v->cls->tp_name, w->cls->tp_name, z->cls->tp_name);
return NULL;
}
extern "C" PyObject* PySequence_Concat(PyObject* s, PyObject* o) noexcept {
PySequenceMethods* m;
......@@ -1392,9 +1535,8 @@ extern "C" PyObject* PyNumber_Divmod(PyObject* lhs, PyObject* rhs) noexcept {
}
}
extern "C" PyObject* PyNumber_Power(PyObject*, PyObject*, PyObject* o3) noexcept {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
extern "C" PyObject* PyNumber_Power(PyObject* v, PyObject* w, PyObject* z) noexcept {
return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
}
extern "C" PyObject* PyNumber_Negative(PyObject* o) noexcept {
......@@ -1421,9 +1563,13 @@ extern "C" PyObject* PyNumber_Invert(PyObject* o) noexcept {
return nullptr;
}
extern "C" PyObject* PyNumber_Lshift(PyObject*, PyObject*) noexcept {
extern "C" PyObject* PyNumber_Lshift(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::LShift);
} catch (ExcInfo e) {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
}
}
extern "C" PyObject* PyNumber_Rshift(PyObject* lhs, PyObject* rhs) noexcept {
......@@ -1684,8 +1830,21 @@ extern "C" PyObject* PyNumber_Index(PyObject* o) noexcept {
return o;
}
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
if (PyIndex_Check(o)) {
result = o->cls->tp_as_number->nb_index(o);
if (result && !PyInt_Check(result) && !PyLong_Check(result)) {
PyErr_Format(PyExc_TypeError, "__index__ returned non-(int,long) "
"(type %.200s)",
result->cls->tp_name);
Py_DECREF(result);
return NULL;
}
} else {
PyErr_Format(PyExc_TypeError, "'%.200s' object cannot be interpreted "
"as an index",
o->cls->tp_name);
}
return result;
}
extern "C" PyObject* PyNumber_ToBase(PyObject* n, int base) noexcept {
......@@ -1693,18 +1852,42 @@ extern "C" PyObject* PyNumber_ToBase(PyObject* n, int base) noexcept {
return nullptr;
}
extern "C" Py_ssize_t PyNumber_AsSsize_t(PyObject* o, PyObject* exc) noexcept {
if (isSubclass(o->cls, int_cls)) {
int64_t n = static_cast<BoxedInt*>(o)->n;
static_assert(sizeof(n) == sizeof(Py_ssize_t), "");
return n;
} else if (isSubclass(o->cls, long_cls)) {
return PyLong_AsSsize_t(o);
extern "C" Py_ssize_t PyNumber_AsSsize_t(PyObject* item, PyObject* err) noexcept {
Py_ssize_t result;
PyObject* runerr;
PyObject* value = PyNumber_Index(item);
if (value == NULL)
return -1;
/* We're done if PyInt_AsSsize_t() returns without error. */
result = PyInt_AsSsize_t(value);
if (result != -1 || !(runerr = PyErr_Occurred()))
goto finish;
/* Error handling code -- only manage OverflowError differently */
if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
goto finish;
PyErr_Clear();
/* If no error-handling desired then the default clipping
is sufficient.
*/
if (!err) {
assert(PyLong_Check(value));
/* Whether or not it is less than or equal to
zero is determined by the sign of ob_size
*/
if (_PyLong_Sign(value) < 0)
result = PY_SSIZE_T_MIN;
else
result = PY_SSIZE_T_MAX;
} else {
/* Otherwise replace the error with caller's error object. */
PyErr_Format(err, "cannot fit '%.200s' into an index-sized integer", item->cls->tp_name);
}
PyErr_Format(PyExc_TypeError, "'%.200s' object cannot be interpreted "
"as an index",
o->cls->tp_name);
return -1;
finish:
Py_DECREF(value);
return result;
}
}
......@@ -750,6 +750,12 @@ Box* divmod(Box* lhs, Box* rhs) {
return binopInternal(lhs, rhs, AST_TYPE::DivMod, false, NULL);
}
Box* powFunc(Box* x, Box* y, Box* z) {
Box* rtn = PyNumber_Power(x, y, z);
checkAndThrowCAPIException();
return rtn;
}
Box* execfile(Box* _fn) {
// The "globals" and "locals" arguments aren't implemented for now
if (!isSubclass(_fn->cls, str_cls)) {
......@@ -1082,6 +1088,8 @@ void setupBuiltins() {
Box* hasattr_obj = new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)hasattr, BOXED_BOOL, 2), "hasattr");
builtins_module->giveAttr("hasattr", hasattr_obj);
builtins_module->giveAttr("pow", new BoxedBuiltinFunctionOrMethod(
boxRTFunction((void*)powFunc, UNKNOWN, 3, 1, false, false), "pow", { None }));
Box* isinstance_obj
= new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)isinstance_func, BOXED_BOOL, 2), "isinstance");
......
......@@ -38,9 +38,9 @@ namespace pyston {
BoxedClass* method_cls;
extern "C" bool _PyIndex_Check(PyObject* op) noexcept {
// TODO this is wrong (the CPython version checks for things that can be coerced to a number):
return PyInt_Check(op);
extern "C" bool _PyIndex_Check(PyObject* obj) noexcept {
return (Py_TYPE(obj)->tp_as_number != NULL && PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_HAVE_INDEX)
&& Py_TYPE(obj)->tp_as_number->nb_index != NULL);
}
extern "C" bool _PyObject_CheckBuffer(PyObject* obj) noexcept {
......
......@@ -488,6 +488,29 @@ static Box* instanceHash(BoxedInstance* inst) {
}
}
static PyObject* instance_index(PyObject* self) noexcept {
PyObject* func, *res;
/*
static PyObject* indexstr = NULL;
if (indexstr == NULL) {
indexstr = PyString_InternFromString("__index__");
if (indexstr == NULL)
return NULL;
}
*/
if ((func = instance_getattro(self, boxString("__index__"))) == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
PyErr_Clear();
PyErr_SetString(PyExc_TypeError, "object cannot be interpreted as an index");
return NULL;
}
res = PyEval_CallObject(func, (PyObject*)NULL);
Py_DECREF(func);
return res;
}
Box* instanceCall(Box* _inst, Box* _args, Box* _kwargs) {
assert(_inst->cls == instance_cls);
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
......@@ -541,5 +564,6 @@ void setupClassobj() {
instance_cls->freeze();
instance_cls->tp_getattro = instance_getattro;
instance_cls->tp_setattro = instance_setattro;
instance_cls->tp_as_number->nb_index = instance_index;
}
}
......@@ -390,20 +390,27 @@ extern "C" Box* floatRMod(BoxedFloat* lhs, Box* rhs) {
}
}
extern "C" Box* floatPowFloat(BoxedFloat* lhs, BoxedFloat* rhs) {
extern "C" Box* floatPowFloat(BoxedFloat* lhs, BoxedFloat* rhs, Box* mod = None) {
assert(lhs->cls == float_cls);
assert(rhs->cls == float_cls);
if (mod != None)
raiseExcHelper(TypeError, "pow() 3rd argument not allowed unless all arguments are integers");
return boxFloat(pow(lhs->d, rhs->d));
}
extern "C" Box* floatPowInt(BoxedFloat* lhs, BoxedInt* rhs) {
extern "C" Box* floatPowInt(BoxedFloat* lhs, BoxedInt* rhs, Box* mod = None) {
assert(lhs->cls == float_cls);
assert(isSubclass(rhs->cls, int_cls));
if (mod != None)
raiseExcHelper(TypeError, "pow() 3rd argument not allowed unless all arguments are integers");
return boxFloat(pow(lhs->d, rhs->n));
}
extern "C" Box* floatPow(BoxedFloat* lhs, Box* rhs) {
extern "C" Box* floatPow(BoxedFloat* lhs, Box* rhs, Box* mod) {
assert(lhs->cls == float_cls);
if (mod != None)
raiseExcHelper(TypeError, "pow() 3rd argument not allowed unless all arguments are integers");
if (isSubclass(rhs->cls, int_cls)) {
return floatPowInt(lhs, static_cast<BoxedInt*>(rhs));
} else if (rhs->cls == float_cls) {
......@@ -708,6 +715,19 @@ static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* flo
float_cls->giveAttr(name, new BoxedFunction(cl));
}
static void _addFuncPow(const char* name, ConcreteCompilerType* rtn_type, void* float_func, void* int_func,
void* boxed_func) {
std::vector<ConcreteCompilerType*> v_ffu{ BOXED_FLOAT, BOXED_FLOAT, UNKNOWN };
std::vector<ConcreteCompilerType*> v_fiu{ BOXED_FLOAT, BOXED_INT, UNKNOWN };
std::vector<ConcreteCompilerType*> v_fuu{ BOXED_FLOAT, UNKNOWN, UNKNOWN };
CLFunction* cl = createRTFunction(3, 1, false, false);
addRTFunction(cl, float_func, rtn_type, v_ffu);
addRTFunction(cl, int_func, rtn_type, v_fiu);
addRTFunction(cl, boxed_func, UNKNOWN, v_fuu);
float_cls->giveAttr(name, new BoxedFunction(cl, { None }));
}
void setupFloat() {
_addFunc("__add__", BOXED_FLOAT, (void*)floatAddFloat, (void*)floatAddInt, (void*)floatAdd);
float_cls->giveAttr("__radd__", float_cls->getattr("__add__"));
......@@ -729,7 +749,7 @@ void setupFloat() {
_addFunc("__mul__", BOXED_FLOAT, (void*)floatMulFloat, (void*)floatMulInt, (void*)floatMul);
float_cls->giveAttr("__rmul__", float_cls->getattr("__mul__"));
_addFunc("__pow__", BOXED_FLOAT, (void*)floatPowFloat, (void*)floatPowInt, (void*)floatPow);
_addFuncPow("__pow__", BOXED_FLOAT, (void*)floatPowFloat, (void*)floatPowInt, (void*)floatPow);
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
_addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
......
......@@ -13,6 +13,7 @@
// limitations under the License.
#include "core/types.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -134,25 +135,22 @@ Box* xrange(Box* cls, Box* start, Box* stop, Box** args) {
Box* step = args[0];
if (stop == NULL) {
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start));
i64 istop = static_cast<BoxedInt*>(start)->n;
i64 istop = PyLong_AsLong(start);
checkAndThrowCAPIException();
return new BoxedXrange(0, istop, 1);
} else if (step == NULL) {
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start));
RELEASE_ASSERT(isSubclass(stop->cls, int_cls), "%s", getTypeName(stop));
i64 istart = static_cast<BoxedInt*>(start)->n;
i64 istop = static_cast<BoxedInt*>(stop)->n;
i64 istart = PyLong_AsLong(start);
checkAndThrowCAPIException();
i64 istop = PyLong_AsLong(stop);
checkAndThrowCAPIException();
return new BoxedXrange(istart, istop, 1);
} else {
RELEASE_ASSERT(isSubclass(start->cls, int_cls), "%s", getTypeName(start));
RELEASE_ASSERT(isSubclass(stop->cls, int_cls), "%s", getTypeName(stop));
RELEASE_ASSERT(isSubclass(step->cls, int_cls), "%s", getTypeName(step));
i64 istart = static_cast<BoxedInt*>(start)->n;
i64 istop = static_cast<BoxedInt*>(stop)->n;
i64 istep = static_cast<BoxedInt*>(step)->n;
i64 istart = PyLong_AsLong(start);
checkAndThrowCAPIException();
i64 istop = PyLong_AsLong(stop);
checkAndThrowCAPIException();
i64 istep = PyLong_AsLong(step);
checkAndThrowCAPIException();
RELEASE_ASSERT(istep != 0, "step can't be 0");
return new BoxedXrange(istart, istop, istep);
}
......
......@@ -58,8 +58,20 @@ extern "C" long PyInt_AsLong(PyObject* op) noexcept {
}
extern "C" Py_ssize_t PyInt_AsSsize_t(PyObject* op) noexcept {
RELEASE_ASSERT(isSubclass(op->cls, int_cls), "");
return static_cast<BoxedInt*>(op)->n;
if (op == NULL) {
PyErr_SetString(PyExc_TypeError, "an integer is required");
return -1;
}
if (PyInt_Check(op))
return ((BoxedInt*)op)->n;
if (PyLong_Check(op))
return _PyLong_AsSsize_t(op);
#if SIZEOF_SIZE_T == SIZEOF_LONG
return PyInt_AsLong(op);
#else
RELEASE_ASSERT("not implemented", "");
#endif
}
extern "C" PyObject* PyInt_FromSize_t(size_t ival) noexcept {
......@@ -758,14 +770,18 @@ extern "C" Box* intPowFloat(BoxedInt* lhs, BoxedFloat* rhs) {
return boxFloat(pow(lhs->n, rhs->d));
}
extern "C" Box* intPow(BoxedInt* lhs, Box* rhs) {
extern "C" Box* intPow(BoxedInt* lhs, Box* rhs, Box* mod) {
if (!isSubclass(lhs->cls, int_cls))
raiseExcHelper(TypeError, "descriptor '__pow__' requires a 'int' object but received a '%s'", getTypeName(lhs));
if (isSubclass(rhs->cls, int_cls)) {
BoxedInt* rhs_int = static_cast<BoxedInt*>(rhs);
return intPowInt(lhs, rhs_int);
Box* rtn = intPowInt(lhs, rhs_int);
if (mod == None)
return rtn;
return binop(rtn, mod, AST_TYPE::Mod);
} else if (rhs->cls == float_cls) {
RELEASE_ASSERT(mod == None, "");
BoxedFloat* rhs_float = static_cast<BoxedFloat*>(rhs);
return intPowFloat(lhs, rhs_float);
} else {
......@@ -924,6 +940,12 @@ extern "C" Box* intTrunc(BoxedInt* self) {
return self;
}
extern "C" Box* intIndex(BoxedInt* v) {
if (PyInt_CheckExact(v))
return v;
return boxInt(v->n);
}
static Box* _intNew(Box* val, Box* base) {
if (isSubclass(val->cls, int_cls)) {
RELEASE_ASSERT(!base, "");
......@@ -1057,7 +1079,8 @@ void setupInt() {
_addFuncIntFloatUnknown("__truediv__", (void*)intTruedivInt, (void*)intTruedivFloat, (void*)intTruediv);
_addFuncIntFloatUnknown("__mul__", (void*)intMulInt, (void*)intMulFloat, (void*)intMul);
_addFuncIntUnknown("__mod__", BOXED_INT, (void*)intModInt, (void*)intMod);
_addFuncIntFloatUnknown("__pow__", (void*)intPowInt, (void*)intPowFloat, (void*)intPow);
int_cls->giveAttr("__pow__",
new BoxedFunction(boxRTFunction((void*)intPow, UNKNOWN, 3, 1, false, false), { None }));
_addFuncIntUnknown("__eq__", BOXED_BOOL, (void*)intEqInt, (void*)intEq);
_addFuncIntUnknown("__ne__", BOXED_BOOL, (void*)intNeInt, (void*)intNe);
......@@ -1081,6 +1104,7 @@ void setupInt() {
int_cls->giveAttr("__oct__", new BoxedFunction(boxRTFunction((void*)intOct, STR, 1)));
int_cls->giveAttr("__trunc__", new BoxedFunction(boxRTFunction((void*)intTrunc, BOXED_INT, 1)));
int_cls->giveAttr("__index__", new BoxedFunction(boxRTFunction((void*)intIndex, BOXED_INT, 1)));
int_cls->giveAttr(
"__new__", new BoxedFunction(boxRTFunction((void*)intNew, UNKNOWN, 3, 2, false, false), { boxInt(0), NULL }));
......
......@@ -192,8 +192,11 @@ extern "C" Box* listGetitemSlice(BoxedList* self, BoxedSlice* slice) {
extern "C" Box* listGetitem(BoxedList* self, Box* slice) {
assert(isSubclass(self->cls, list_cls));
if (isSubclass(slice->cls, int_cls)) {
return listGetitemInt(self, static_cast<BoxedInt*>(slice));
if (PyIndex_Check(slice)) {
Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
throwCAPIException();
return listGetitemUnboxed(self, i);
} else if (slice->cls == slice_cls) {
return listGetitemSlice(self, static_cast<BoxedSlice*>(slice));
} else {
......@@ -212,23 +215,23 @@ static void _listSetitem(BoxedList* self, int64_t n, Box* v) {
self->elts->elts[n] = v;
}
extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) {
extern "C" Box* listSetitemUnboxed(BoxedList* self, int64_t n, Box* v) {
// I think r lock is ok here, since we don't change the list structure:
LOCK_REGION(self->lock.asRead());
assert(isSubclass(self->cls, list_cls));
assert(isSubclass(slice->cls, int_cls));
int64_t n = slice->n;
_listSetitem(self, n, v);
return None;
}
extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) {
assert(isSubclass(slice->cls, int_cls));
return listSetitemUnboxed(self, slice->n, v);
}
extern "C" int PyList_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) noexcept {
assert(isSubclass(op->cls, list_cls));
try {
_listSetitem(static_cast<BoxedList*>(op), i, newitem);
listSetitemUnboxed(static_cast<BoxedList*>(op), i, newitem);
} catch (ExcInfo e) {
abort();
}
......@@ -460,8 +463,12 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
extern "C" Box* listSetitem(BoxedList* self, Box* slice, Box* v) {
assert(isSubclass(self->cls, list_cls));
if (isSubclass(slice->cls, int_cls)) {
return listSetitemInt(self, static_cast<BoxedInt*>(slice), v);
if (PyIndex_Check(slice)) {
Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
throwCAPIException();
listSetitemUnboxed(self, i, v);
return None;
} else if (slice->cls == slice_cls) {
return listSetitemSlice(self, static_cast<BoxedSlice*>(slice), v);
} else {
......@@ -492,9 +499,11 @@ extern "C" Box* listDelitem(BoxedList* self, Box* slice) {
LOCK_REGION(self->lock.asWrite());
Box* rtn;
if (isSubclass(slice->cls, int_cls)) {
rtn = listDelitemInt(self, static_cast<BoxedInt*>(slice));
if (PyIndex_Check(slice)) {
Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
throwCAPIException();
rtn = listDelitemInt(self, (BoxedInt*)boxInt(i));
} else if (slice->cls == slice_cls) {
rtn = listDelitemSlice(self, static_cast<BoxedSlice*>(slice));
} else {
......
This diff is collapsed.
......@@ -47,7 +47,7 @@ Box* longAdd(BoxedLong* lhs, Box* rhs);
Box* longSub(BoxedLong* lhs, Box* rhs);
Box* longMul(BoxedLong* lhs, Box* rhs);
Box* longDiv(BoxedLong* lhs, Box* rhs);
Box* longPow(BoxedLong* lhs, Box* rhs);
Box* longPow(BoxedLong* lhs, Box* rhs, Box* mod = None);
Box* longLshift(BoxedLong* lhs, Box* rhs);
Box* longRshift(BoxedLong* lhs, Box* rhs);
......
......@@ -326,6 +326,7 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_flags |= Py_TPFLAGS_HAVE_GC;
tp_flags |= Py_TPFLAGS_HAVE_WEAKREFS;
tp_flags |= Py_TPFLAGS_HAVE_RICHCOMPARE;
tp_flags |= Py_TPFLAGS_HAVE_INDEX;
if (base && (base->tp_flags & Py_TPFLAGS_HAVE_NEWBUFFER))
tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
......
......@@ -2240,9 +2240,10 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) {
extern "C" Box* strGetitem(BoxedString* self, Box* slice) {
assert(isSubclass(self->cls, str_cls));
if (isSubclass(slice->cls, int_cls)) {
BoxedInt* islice = static_cast<BoxedInt*>(slice);
int64_t n = islice->n;
if (PyIndex_Check(slice)) {
Py_ssize_t n = PyNumber_AsSsize_t(slice, PyExc_IndexError);
if (n == -1 && PyErr_Occurred())
throwCAPIException();
int size = self->size();
if (n < 0)
n = size + n;
......
......@@ -23,6 +23,7 @@
#include "core/stats.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
......@@ -146,9 +147,12 @@ int BoxedTuple::Resize(BoxedTuple** pv, size_t newsize) noexcept {
Box* tupleGetitem(BoxedTuple* self, Box* slice) {
assert(self->cls == tuple_cls);
if (isSubclass(slice->cls, int_cls))
return tupleGetitemInt(self, static_cast<BoxedInt*>(slice));
else if (slice->cls == slice_cls)
if (PyIndex_Check(slice)) {
Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError);
if (i == -1 && PyErr_Occurred())
throwCAPIException();
return tupleGetitemUnboxed(self, i);
} else if (slice->cls == slice_cls)
return tupleGetitemSlice(self, static_cast<BoxedSlice*>(slice));
else
raiseExcHelper(TypeError, "tuple indices must be integers, not %s", getTypeName(slice));
......
......@@ -40,6 +40,8 @@ print isinstance(1, int)
print isinstance(1, (float, int))
print isinstance(1, (float, (), (int, 3), 4))
print pow(11, 42)
print pow(11, 42, 75)
print divmod(5, 2)
print divmod(5L, -2)
try:
......
# expected: fail
# - long % int
import sys
P = 1000000007
......
class Index(object):
def __init__(self, i):
self.i = i
def __index__(self):
print "called __index__"
return self.i
s = "String"
l = [1, 2, "List"]
t = (1, 2, "Tuple")
print s[Index(2L)]
print l[Index(2L)]
print t[Index(2L)]
......@@ -13,6 +13,9 @@ for i in xrange(1, 12):
print 1 ** 0
print 0 ** 0
print -1 ** 0
print (11).__pow__(5, 50)
print (11).__pow__(32, 50)
print (11).__index__()
for i in (-10, 10, 0, -15):
print i, i.__hex__(), i.__oct__()
......
......@@ -4,6 +4,7 @@ print l * 5
l[0] = 1
print l
print l[2]
print l[2L]
l = range(5)
while l:
......
......@@ -13,6 +13,7 @@ def test(a, b):
print a - b, b - a, a.__sub__(b), b.__sub__(a)
print a * b, b * a, a.__mul__(b), b.__mul__(a)
print a / b, b / a, a.__div__(b), b.__div__(a)
print a % b, b % a, a.__mod__(b), b.__mod__(a)
print repr(a), repr(b), a < b, a > b, a <= b, a >= b, a == b, a != b
if not isinstance(a, float) and not isinstance(b, float):
print a ^ b, a | b, a & b
......@@ -55,10 +56,15 @@ print ~(-10L)
print -(1L)
print 1L**2L
print 1L**2
print (11L).__pow__(32, 50L)
print (11L).__index__()
print long("100", 16)
print long("100", 10)
print long("100", 26)
print long("0x100", 16), long("0100", 8), long("0b100", 2)
print long("0x100", 0), long("0100", 0), long("0b100", 0)
print long("0b100", 16), long("0b100L", 0), long("-0b100L", 0)
print long(-1.1)
print long(1.9)
print long(-1.9)
......
......@@ -133,6 +133,7 @@ except TypeError, e:
t = (1, "2")
print t[0]
print t[1]
print t[1L]
t = (1, 2, 'a', 'b', 'c')
print t[::-1]
......
......@@ -15,3 +15,6 @@ for i in xrange(10, -10, -3):
for i in xrange(0):
print i
for i in xrange(10L, 15L, 1L):
print i
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