Commit f95bd65f authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #467 from undingen/pycrypto

Misc stuff for pycrypto
parents a53ab1a8 1dc72576
......@@ -93,7 +93,7 @@ endif()
add_subdirectory(${DEPS_DIR}/llvm-trunk ${CMAKE_BINARY_DIR}/llvm EXCLUDE_FROM_ALL)
set(CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}/llvm/share/llvm/cmake/")
include(LLVMConfig)
llvm_map_components_to_libnames(LLVM_LIBS core mcjit native bitreader ipo irreader debuginfodwarf instrumentation ${INTEL_JIT_EVENTS_LIB})
llvm_map_components_to_libnames(LLVM_LIBS core mcjit native bitreader bitwriter ipo irreader debuginfodwarf instrumentation ${INTEL_JIT_EVENTS_LIB})
# libunwind
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
......
......@@ -97,7 +97,7 @@ else
LLVM_BIN := $(LLVM_BUILD)/Release/bin
endif
LLVM_LINK_LIBS := core mcjit native bitreader ipo irreader debuginfodwarf instrumentation
LLVM_LINK_LIBS := core mcjit native bitreader bitwriter ipo irreader debuginfodwarf instrumentation
ifneq ($(ENABLE_INTEL_JIT_EVENTS),0)
LLVM_LINK_LIBS += inteljitevents
endif
......
......@@ -155,6 +155,10 @@ def libc_ver(executable=sys.executable,lib='',version='',
The file is read and scanned in chunks of chunksize bytes.
"""
# Pyston change: hard code pyston executable libc version
if executable == sys.executable:
return ("glibc", "2.6")
if hasattr(os.path, 'realpath'):
# Python 2.2 introduced os.path.realpath(); it is used
# here to work around problems with Cygwin not being
......
Subproject commit 8f62d5d7440cff89f98ed5a2e7756321811a0f2d
Subproject commit 51f55dd4068f116ca287369cedddce624de73da6
......@@ -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 {
fatalOrError(PyExc_NotImplementedError, "unimplemented");
return nullptr;
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;
}
}
......@@ -281,7 +281,7 @@ public:
// Generate a hash for the module
HashOStream hash_stream;
M->print(hash_stream, 0);
llvm::WriteBitcodeToFile(M, hash_stream);
hash_before_codegen = hash_stream.getHash();
llvm::SmallString<128> cache_file = cache_dir;
......
......@@ -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);
......
......@@ -589,7 +589,9 @@ extern "C" PyObject* PyImport_ImportModule(const char* name) noexcept {
try {
// TODO: check if this has the same behaviour as the cpython implementation
std::string str = name;
return import(0, None, &str);
BoxedList* silly_list = new BoxedList();
listAppendInternal(silly_list, boxString("__doc__"));
return import(0, silly_list, &str);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
......
......@@ -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));
......
......@@ -956,16 +956,61 @@ extern "C" int PySlice_GetIndices(PySliceObject* r, Py_ssize_t length, Py_ssize_
extern "C" int PySlice_GetIndicesEx(PySliceObject* _r, Py_ssize_t length, Py_ssize_t* start, Py_ssize_t* stop,
Py_ssize_t* step, Py_ssize_t* slicelength) noexcept {
try {
BoxedSlice* r = (BoxedSlice*)_r;
assert(r->cls == slice_cls);
// parseSlice has the exact same behaviour as CPythons PySlice_GetIndicesEx apart from throwing c++ exceptions
// on error.
parseSlice(r, length, start, stop, step, slicelength);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
BoxedSlice* r = (BoxedSlice*)_r;
RELEASE_ASSERT(r->cls == slice_cls, "");
/* this is harder to get right than you might think */
Py_ssize_t defstart, defstop;
if (r->step == Py_None) {
*step = 1;
} else {
if (!_PyEval_SliceIndex(r->step, step))
return -1;
if (*step == 0) {
PyErr_SetString(PyExc_ValueError, "slice step cannot be zero");
return -1;
}
}
defstart = *step < 0 ? length - 1 : 0;
defstop = *step < 0 ? -1 : length;
if (r->start == Py_None) {
*start = defstart;
} else {
if (!_PyEval_SliceIndex(r->start, start))
return -1;
if (*start < 0)
*start += length;
if (*start < 0)
*start = (*step < 0) ? -1 : 0;
if (*start >= length)
*start = (*step < 0) ? length - 1 : length;
}
if (r->stop == Py_None) {
*stop = defstop;
} else {
if (!_PyEval_SliceIndex(r->stop, stop))
return -1;
if (*stop < 0)
*stop += length;
if (*stop < 0)
*stop = (*step < 0) ? -1 : 0;
if (*stop >= length)
*stop = (*step < 0) ? length - 1 : length;
}
if ((*step < 0 && *stop >= *start) || (*step > 0 && *start >= *stop)) {
*slicelength = 0;
} else if (*step < 0) {
*slicelength = (*stop - *start + 1) / (*step) + 1;
} else {
*slicelength = (*stop - *start - 1) / (*step) + 1;
}
return 0;
}
......
......@@ -15,84 +15,15 @@
#include "runtime/util.h"
#include "core/options.h"
#include "runtime/capi.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
namespace pyston {
// Provides the exact same behaviour as CPythons PySlice_GetIndicesEx apart from throwing c++ exceptions on error
void parseSlice(BoxedSlice* slice, int size, i64* out_start, i64* out_stop, i64* out_step, i64* out_length) {
BoxedSlice* sslice = static_cast<BoxedSlice*>(slice);
Box* start = sslice->start;
assert(start);
Box* stop = sslice->stop;
assert(stop);
Box* step = sslice->step;
assert(step);
RELEASE_ASSERT(isSubclass(start->cls, int_cls) || start->cls == none_cls, "");
RELEASE_ASSERT(isSubclass(stop->cls, int_cls) || stop->cls == none_cls, "");
RELEASE_ASSERT(isSubclass(step->cls, int_cls) || step->cls == none_cls, "");
int64_t istart;
int64_t istop;
int64_t istep = 1;
if (isSubclass(step->cls, int_cls)) {
istep = static_cast<BoxedInt*>(step)->n;
if (istep == 0) {
raiseExcHelper(ValueError, "slice step cannot be zero");
}
}
if (isSubclass(start->cls, int_cls)) {
istart = static_cast<BoxedInt*>(start)->n;
if (istart < 0)
istart = size + istart;
} else {
if (istep > 0)
istart = 0;
else
istart = size - 1;
}
if (isSubclass(stop->cls, int_cls)) {
istop = static_cast<BoxedInt*>(stop)->n;
if (istop < 0)
istop = size + istop;
} else {
if (istep > 0)
istop = size;
else
istop = -1;
}
if (istep > 0) {
if (istart < 0)
istart = 0;
if (istop > size)
istop = size;
} else {
if (istart >= size)
istart = size - 1;
if (istop < 0)
istop = -1;
}
*out_start = istart;
*out_stop = istop;
*out_step = istep;
if (out_length) {
// This is adapted from CPython's PySlice_GetIndicesEx.
if ((istep < 0 && istop >= istart) || (istep > 0 && istart >= istop))
*out_length = 0;
else if (istep < 0)
*out_length = (istop - istart + 1) / istep + 1;
else
*out_length = (istop - istart - 1) / istep + 1;
RELEASE_ASSERT(*out_length >= 0, "negative length, should never happen");
}
int ret = PySlice_GetIndicesEx((PySliceObject*)slice, size, out_start, out_stop, out_step, out_length);
if (ret == -1)
throwCAPIException();
}
}
......@@ -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