Commit 109df648 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #783 from rudi-c/numpy_fix

Some work on the NumPy test
parents 76c42191 d837de31
...@@ -134,6 +134,13 @@ PyObject* PyGC_AddRoot(PyObject*) PYSTON_NOEXCEPT; ...@@ -134,6 +134,13 @@ PyObject* PyGC_AddRoot(PyObject*) PYSTON_NOEXCEPT;
// PyGC_AddRoot(obj); // PyGC_AddRoot(obj);
// to reduce any chances of compiler reorderings or a GC somehow happening between the assignment // to reduce any chances of compiler reorderings or a GC somehow happening between the assignment
// to the static slot and the call to PyGC_AddRoot. // to the static slot and the call to PyGC_AddRoot.
//
// Similarly, some extension modules have static non-type objects that our GC thinks are errors
// since they are not in the heap, unless we root them. This function should be used purely as
// a temporary patching mechanism - we want to have a better way of dealing with such objects
// in the future (even if it's an invalid use of CPython APIs).
PyObject* PyGC_AddNonHeapRoot(PyObject* obj, int size) PYSTON_NOEXCEPT;
// Pyston change : expose these type objects // Pyston change : expose these type objects
extern PyTypeObject Pattern_Type; extern PyTypeObject Pattern_Type;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define SIZEOF__BOOL 1 #define SIZEOF__BOOL 1
#define SIZEOF_VOID_P 8 #define SIZEOF_VOID_P 8
#define SIZEOF_SIZE_T 8 #define SIZEOF_SIZE_T 8
#define SIZEOF_SHORT 2
#define SIZEOF_INT 4 #define SIZEOF_INT 4
#define SIZEOF_LONG 8 #define SIZEOF_LONG 8
#define SIZEOF_LONG_LONG 8 #define SIZEOF_LONG_LONG 8
......
...@@ -524,6 +524,7 @@ public: ...@@ -524,6 +524,7 @@ public:
// bool visit_classdef(AST_ClassDef *node) override { return false; } // bool visit_classdef(AST_ClassDef *node) override { return false; }
bool visit_continue(AST_Continue* node) override { return false; } bool visit_continue(AST_Continue* node) override { return false; }
bool visit_dict(AST_Dict* node) override { return false; } bool visit_dict(AST_Dict* node) override { return false; }
bool visit_ellipsis(AST_Ellipsis* node) override { return false; }
bool visit_excepthandler(AST_ExceptHandler* node) override { return false; } bool visit_excepthandler(AST_ExceptHandler* node) override { return false; }
bool visit_expr(AST_Expr* node) override { return false; } bool visit_expr(AST_Expr* node) override { return false; }
bool visit_extslice(AST_ExtSlice* node) override { return false; } bool visit_extslice(AST_ExtSlice* node) override { return false; }
......
...@@ -3270,7 +3270,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -3270,7 +3270,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
| Py_TPFLAGS_DICT_SUBCLASS | Py_TPFLAGS_BASE_EXC_SUBCLASS | Py_TPFLAGS_TYPE_SUBCLASS; | Py_TPFLAGS_DICT_SUBCLASS | Py_TPFLAGS_BASE_EXC_SUBCLASS | Py_TPFLAGS_TYPE_SUBCLASS;
RELEASE_ASSERT((cls->tp_flags & ~ALLOWABLE_FLAGS) == 0, ""); RELEASE_ASSERT((cls->tp_flags & ~ALLOWABLE_FLAGS) == 0, "");
RELEASE_ASSERT(cls->tp_free == NULL || cls->tp_free == PyObject_Del || cls->tp_free == PyObject_GC_Del, "");
RELEASE_ASSERT(cls->tp_is_gc == NULL, ""); RELEASE_ASSERT(cls->tp_is_gc == NULL, "");
RELEASE_ASSERT(cls->tp_mro == NULL, ""); RELEASE_ASSERT(cls->tp_mro == NULL, "");
RELEASE_ASSERT(cls->tp_cache == NULL, ""); RELEASE_ASSERT(cls->tp_cache == NULL, "");
...@@ -3301,6 +3300,19 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -3301,6 +3300,19 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
assert(cls->tp_name); assert(cls->tp_name);
// Inherit some special protocols. Normally methods are automatically inherited,
// when a Python class is declared, but that may not be the case with C extensions.
if (base != NULL) {
if (cls->tp_as_number == NULL)
cls->tp_as_number = base->tp_as_number;
if (cls->tp_as_sequence == NULL)
cls->tp_as_sequence = base->tp_as_sequence;
if (cls->tp_as_mapping == NULL)
cls->tp_as_mapping = base->tp_as_mapping;
if (cls->tp_as_buffer == NULL)
cls->tp_as_buffer = base->tp_as_buffer;
}
if (cls->tp_call) { if (cls->tp_call) {
cls->tpp_call.capi_val = tppProxyToTpCall<CAPI>; cls->tpp_call.capi_val = tppProxyToTpCall<CAPI>;
cls->tpp_call.cxx_val = tppProxyToTpCall<CXX>; cls->tpp_call.cxx_val = tppProxyToTpCall<CXX>;
......
...@@ -384,6 +384,12 @@ AST_DictComp* read_dictcomp(BufferedReader* reader) { ...@@ -384,6 +384,12 @@ AST_DictComp* read_dictcomp(BufferedReader* reader) {
return rtn; return rtn;
} }
AST_Ellipsis* read_ellipsis(BufferedReader* reader) {
AST_Ellipsis* rtn = new AST_Ellipsis();
rtn->col_offset = -1;
rtn->lineno = -1;
return rtn;
}
AST_ExceptHandler* read_excepthandler(BufferedReader* reader) { AST_ExceptHandler* read_excepthandler(BufferedReader* reader) {
AST_ExceptHandler* rtn = new AST_ExceptHandler(); AST_ExceptHandler* rtn = new AST_ExceptHandler();
...@@ -822,6 +828,8 @@ AST_expr* readASTExpr(BufferedReader* reader) { ...@@ -822,6 +828,8 @@ AST_expr* readASTExpr(BufferedReader* reader) {
return read_dict(reader); return read_dict(reader);
case AST_TYPE::DictComp: case AST_TYPE::DictComp:
return read_dictcomp(reader); return read_dictcomp(reader);
case AST_TYPE::Ellipsis:
return read_ellipsis(reader);
case AST_TYPE::ExtSlice: case AST_TYPE::ExtSlice:
return read_extslice(reader); return read_extslice(reader);
case AST_TYPE::GeneratorExp: case AST_TYPE::GeneratorExp:
......
...@@ -277,6 +277,7 @@ private: ...@@ -277,6 +277,7 @@ private:
writeExpr(node->value); writeExpr(node->value);
return true; return true;
} }
virtual bool visit_ellipsis(AST_Ellipsis* node) { return true; }
virtual bool visit_excepthandler(AST_ExceptHandler* node) { virtual bool visit_excepthandler(AST_ExceptHandler* node) {
writeStmtVector(node->body); writeStmtVector(node->body);
writeColOffset(node->col_offset); writeColOffset(node->col_offset);
......
...@@ -2034,6 +2034,10 @@ public: ...@@ -2034,6 +2034,10 @@ public:
output->push_back(node); output->push_back(node);
return false; return false;
} }
virtual bool visit_ellipsis(AST_Ellipsis* node) {
output->push_back(node);
return false;
}
virtual bool visit_excepthandler(AST_ExceptHandler* node) { virtual bool visit_excepthandler(AST_ExceptHandler* node) {
output->push_back(node); output->push_back(node);
return false; return false;
......
...@@ -855,6 +855,8 @@ private: ...@@ -855,6 +855,8 @@ private:
return rtn; return rtn;
} }
AST_expr* remapEllipsis(AST_Ellipsis* node) { return node; }
AST_expr* remapExtSlice(AST_ExtSlice* node) { AST_expr* remapExtSlice(AST_ExtSlice* node) {
AST_ExtSlice* rtn = new AST_ExtSlice(); AST_ExtSlice* rtn = new AST_ExtSlice();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
...@@ -1183,6 +1185,9 @@ private: ...@@ -1183,6 +1185,9 @@ private:
case AST_TYPE::DictComp: case AST_TYPE::DictComp:
rtn = remapScopedComprehension<AST_Dict>(ast_cast<AST_DictComp>(node)); rtn = remapScopedComprehension<AST_Dict>(ast_cast<AST_DictComp>(node));
break; break;
case AST_TYPE::Ellipsis:
rtn = remapEllipsis(ast_cast<AST_Ellipsis>(node));
break;
case AST_TYPE::ExtSlice: case AST_TYPE::ExtSlice:
rtn = remapExtSlice(ast_cast<AST_ExtSlice>(node)); rtn = remapExtSlice(ast_cast<AST_ExtSlice>(node));
break; break;
......
...@@ -243,6 +243,13 @@ extern "C" PyObject* PyGC_AddRoot(PyObject* obj) noexcept { ...@@ -243,6 +243,13 @@ extern "C" PyObject* PyGC_AddRoot(PyObject* obj) noexcept {
return obj; return obj;
} }
extern "C" PyObject* PyGC_AddNonHeapRoot(PyObject* obj, int size) noexcept {
if (obj) {
registerNonheapRootObject(obj, size);
}
return obj;
}
void registerNonheapRootObject(void* obj, int size) { void registerNonheapRootObject(void* obj, int size) {
// I suppose that things could work fine even if this were true, but why would it happen? // I suppose that things could work fine even if this were true, but why would it happen?
assert(global_heap.getAllocationFromInteriorPointer(obj) == NULL); assert(global_heap.getAllocationFromInteriorPointer(obj) == NULL);
......
...@@ -31,7 +31,19 @@ extern "C" Box* createPureImaginary(double i) { ...@@ -31,7 +31,19 @@ extern "C" Box* createPureImaginary(double i) {
} }
extern "C" Py_complex PyComplex_AsCComplex(PyObject* op) noexcept { extern "C" Py_complex PyComplex_AsCComplex(PyObject* op) noexcept {
// TODO: Incomplete v.s. CPython's implementation.
Py_complex cval;
if (PyComplex_Check(op)) {
cval.real = ((BoxedComplex*)op)->real;
cval.imag = ((BoxedComplex*)op)->imag;
return cval;
} else if (op->cls == int_cls) {
cval.real = ((BoxedInt*)op)->n;
cval.imag = 0.0;
return cval;
} else {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
}
} }
extern "C" double PyComplex_RealAsDouble(PyObject* op) noexcept { extern "C" double PyComplex_RealAsDouble(PyObject* op) noexcept {
...@@ -255,6 +267,12 @@ Box* complexHash(BoxedComplex* self) { ...@@ -255,6 +267,12 @@ Box* complexHash(BoxedComplex* self) {
return boxInt(combined); return boxInt(combined);
} }
Box* complexAbs(BoxedComplex* self) {
assert(self->cls == complex_cls);
// TODO: CPython does a lot more safety checks.
return boxFloat(sqrt(self->real * self->real + self->imag * self->imag));
}
Box* complexStr(BoxedComplex* self) { Box* complexStr(BoxedComplex* self) {
assert(self->cls == complex_cls); assert(self->cls == complex_cls);
return boxString(complexFmt(self->real, self->imag, 12, 'g')); return boxString(complexFmt(self->real, self->imag, 12, 'g'));
...@@ -364,6 +382,7 @@ void setupComplex() { ...@@ -364,6 +382,7 @@ void setupComplex() {
complex_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)complexPos, BOXED_COMPLEX, 1))); complex_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)complexPos, BOXED_COMPLEX, 1)));
complex_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)complexHash, BOXED_INT, 1))); complex_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)complexHash, BOXED_INT, 1)));
complex_cls->giveAttr("__abs__", new BoxedFunction(boxRTFunction((void*)complexAbs, BOXED_FLOAT, 1)));
complex_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)complexStr, STR, 1))); complex_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)complexStr, STR, 1)));
complex_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)complexRepr, STR, 1))); complex_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)complexRepr, STR, 1)));
complex_cls->giveAttr("real", complex_cls->giveAttr("real",
......
...@@ -174,6 +174,11 @@ Box* dictViewItems(BoxedDict* self) { ...@@ -174,6 +174,11 @@ Box* dictViewItems(BoxedDict* self) {
return rtn; return rtn;
} }
// Analoguous to CPython's, used for sq_ slots.
static Py_ssize_t dict_length(PyDictObject* mp) {
return ((BoxedDict*)mp)->d.size();
}
Box* dictLen(BoxedDict* self) { Box* dictLen(BoxedDict* self) {
if (!isSubclass(self->cls, dict_cls)) if (!isSubclass(self->cls, dict_cls))
raiseExcHelper(TypeError, "descriptor '__len__' requires a 'dict' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__len__' requires a 'dict' object but received a '%s'",
...@@ -374,9 +379,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc ...@@ -374,9 +379,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc
} }
Box* dictSetitem(BoxedDict* self, Box* k, Box* v) { Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
// printf("Starting setitem\n");
Box*& pos = self->d[k]; Box*& pos = self->d[k];
// printf("Got the pos\n");
if (pos != NULL) { if (pos != NULL) {
pos = v; pos = v;
...@@ -402,6 +405,22 @@ Box* dictDelitem(BoxedDict* self, Box* k) { ...@@ -402,6 +405,22 @@ Box* dictDelitem(BoxedDict* self, Box* k) {
return None; return None;
} }
// Analoguous to CPython's, used for sq_ slots.
static int dict_ass_sub(PyDictObject* mp, PyObject* v, PyObject* w) noexcept {
try {
Box* res;
if (w == NULL) {
res = dictDelitem((BoxedDict*)mp, v);
} else {
res = dictSetitem((BoxedDict*)mp, v, w);
}
assert(res == None);
} catch (ExcInfo e) {
setCAPIException(e);
}
return 0;
}
extern "C" int PyDict_DelItem(PyObject* op, PyObject* key) noexcept { extern "C" int PyDict_DelItem(PyObject* op, PyObject* key) noexcept {
ASSERT(isSubclass(op->cls, dict_cls) || op->cls == attrwrapper_cls, "%s", getTypeName(op)); ASSERT(isSubclass(op->cls, dict_cls) || op->cls == attrwrapper_cls, "%s", getTypeName(op));
try { try {
...@@ -820,7 +839,11 @@ void setupDict() { ...@@ -820,7 +839,11 @@ void setupDict() {
dict_cls->tp_init = dict_init; dict_cls->tp_init = dict_init;
dict_cls->tp_repr = dict_repr; dict_cls->tp_repr = dict_repr;
dict_cls->tp_as_mapping->mp_length = (lenfunc)dict_length;
dict_cls->tp_as_mapping->mp_subscript = (binaryfunc)dictGetitem<CAPI>; dict_cls->tp_as_mapping->mp_subscript = (binaryfunc)dictGetitem<CAPI>;
dict_cls->tp_as_mapping->mp_ass_subscript = (objobjargproc)dict_ass_sub;
dict_cls->tp_as_sequence->sq_contains = (objobjproc)PyDict_Contains;
dict_keys_cls->giveAttr( dict_keys_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)dictViewKeysIter, typeFromClass(dict_iterator_cls), 1))); "__iter__", new BoxedFunction(boxRTFunction((void*)dictViewKeysIter, typeFromClass(dict_iterator_cls), 1)));
......
...@@ -809,7 +809,7 @@ BoxedModule* importCExtension(const std::string& full_name, const std::string& l ...@@ -809,7 +809,7 @@ BoxedModule* importCExtension(const std::string& full_name, const std::string& l
// Let the GC know about the static variables. // Let the GC know about the static variables.
uintptr_t bss_start = (uintptr_t)dlsym(handle, "__bss_start"); uintptr_t bss_start = (uintptr_t)dlsym(handle, "__bss_start");
uintptr_t bss_end = (uintptr_t)dlsym(handle, "_end"); uintptr_t bss_end = (uintptr_t)dlsym(handle, "_end");
RELEASE_ASSERT(bss_end - bss_start < 100000, "Large BSS section detected - there maybe something wrong"); RELEASE_ASSERT(bss_end - bss_start < 1000000, "Large BSS section detected - there maybe something wrong");
// only track void* aligned memory // only track void* aligned memory
bss_start = (bss_start + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1); bss_start = (bss_start + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1);
bss_end -= bss_end % sizeof(void*); bss_end -= bss_end % sizeof(void*);
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
namespace pyston { namespace pyston {
static int list_ass_slice(PyListObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject* v);
extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept { extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept {
RELEASE_ASSERT(PyList_Check(op), ""); RELEASE_ASSERT(PyList_Check(op), "");
try { try {
...@@ -198,7 +200,7 @@ static Box* list_slice(Box* o, Py_ssize_t ilow, Py_ssize_t ihigh) noexcept { ...@@ -198,7 +200,7 @@ static Box* list_slice(Box* o, Py_ssize_t ilow, Py_ssize_t ihigh) noexcept {
return (PyObject*)np; return (PyObject*)np;
} }
extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) { static inline Box* listGetitemUnboxed(BoxedList* self, int64_t n) {
assert(isSubclass(self->cls, list_cls)); assert(isSubclass(self->cls, list_cls));
if (n < 0) if (n < 0)
n = self->size + n; n = self->size + n;
...@@ -252,6 +254,17 @@ extern "C" Box* listGetslice(BoxedList* self, Box* boxedStart, Box* boxedStop) { ...@@ -252,6 +254,17 @@ extern "C" Box* listGetslice(BoxedList* self, Box* boxedStart, Box* boxedStop) {
return _listSlice(self, start, stop, 1, stop - start); return _listSlice(self, start, stop, 1, stop - start);
} }
// Analoguous to CPython's, used for sq_ slots.
static PyObject* list_item(PyListObject* a, Py_ssize_t i) noexcept {
try {
BoxedList* self = (BoxedList*)a;
return listGetitemUnboxed(self, i);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
template <ExceptionStyle S> Box* listGetitem(BoxedList* self, Box* slice) { template <ExceptionStyle S> Box* listGetitem(BoxedList* self, Box* slice) {
if (S == CAPI) { if (S == CAPI) {
try { try {
...@@ -297,6 +310,22 @@ extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) { ...@@ -297,6 +310,22 @@ extern "C" Box* listSetitemInt(BoxedList* self, BoxedInt* slice, Box* v) {
return listSetitemUnboxed(self, slice->n, v); return listSetitemUnboxed(self, slice->n, v);
} }
// Analoguous to CPython's, used for sq_ slots.
static int list_ass_item(PyListObject* a, Py_ssize_t i, PyObject* v) {
PyObject* old_value;
if (i < 0 || i >= Py_SIZE(a)) {
PyErr_SetString(PyExc_IndexError, "list assignment index out of range");
return -1;
}
if (v == NULL)
return list_ass_slice(a, i, i + 1, v);
Py_INCREF(v);
old_value = a->ob_item[i];
a->ob_item[i] = v;
Py_DECREF(old_value);
return 0;
}
extern "C" int PyList_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) noexcept { extern "C" int PyList_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) noexcept {
PyObject* olditem; PyObject* olditem;
PyObject** p; PyObject** p;
...@@ -449,7 +478,7 @@ int list_ass_ext_slice(BoxedList* self, PyObject* item, PyObject* value) { ...@@ -449,7 +478,7 @@ int list_ass_ext_slice(BoxedList* self, PyObject* item, PyObject* value) {
} }
} }
Box* listSetitemSliceInt64(BoxedList* self, i64 start, i64 stop, i64 step, Box* v) { static inline void listSetitemSliceInt64(BoxedList* self, i64 start, i64 stop, i64 step, Box* v) {
RELEASE_ASSERT(step == 1, "step sizes must be 1 in this code path"); RELEASE_ASSERT(step == 1, "step sizes must be 1 in this code path");
boundSliceWithLength(&start, &stop, start, stop, self->size); boundSliceWithLength(&start, &stop, start, stop, self->size);
...@@ -488,8 +517,6 @@ Box* listSetitemSliceInt64(BoxedList* self, i64 start, i64 stop, i64 step, Box* ...@@ -488,8 +517,6 @@ Box* listSetitemSliceInt64(BoxedList* self, i64 start, i64 stop, i64 step, Box*
} }
self->size += delts; self->size += delts;
return None;
} }
extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
...@@ -511,7 +538,14 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) { ...@@ -511,7 +538,14 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
return None; return None;
} }
return listSetitemSliceInt64(self, start, stop, step, v); listSetitemSliceInt64(self, start, stop, step, v);
return None;
}
// Analoguous to CPython's, used for sq_ slots.
static int list_ass_slice(PyListObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject* v) {
listSetitemSliceInt64((BoxedList*)a, ilow, ihigh, 1, v);
return 0;
} }
extern "C" Box* listSetslice(BoxedList* self, Box* boxedStart, Box* boxedStop, Box** args) { extern "C" Box* listSetslice(BoxedList* self, Box* boxedStart, Box* boxedStop, Box** args) {
...@@ -522,7 +556,8 @@ extern "C" Box* listSetslice(BoxedList* self, Box* boxedStart, Box* boxedStop, B ...@@ -522,7 +556,8 @@ extern "C" Box* listSetslice(BoxedList* self, Box* boxedStart, Box* boxedStop, B
sliceIndex(boxedStart, &start); sliceIndex(boxedStart, &start);
sliceIndex(boxedStop, &stop); sliceIndex(boxedStop, &stop);
return listSetitemSliceInt64(self, start, stop, 1, value); listSetitemSliceInt64(self, start, stop, 1, value);
return None;
} }
extern "C" Box* listSetitem(BoxedList* self, Box* slice, Box* v) { extern "C" Box* listSetitem(BoxedList* self, Box* slice, Box* v) {
...@@ -822,23 +857,33 @@ extern "C" Box* PyList_GetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh) ...@@ -822,23 +857,33 @@ extern "C" Box* PyList_GetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh)
return listGetitemSlice<CAPI>(self, new BoxedSlice(boxInt(ilow), boxInt(ihigh), boxInt(1))); return listGetitemSlice<CAPI>(self, new BoxedSlice(boxInt(ilow), boxInt(ihigh), boxInt(1)));
} }
Box* listContains(BoxedList* self, Box* elt) { static inline int list_contains_shared(BoxedList* self, Box* elt) {
assert(isSubclass(self->cls, list_cls));
int size = self->size; int size = self->size;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
Box* e = self->elts->elts[i]; Box* e = self->elts->elts[i];
bool identity_eq = e == elt; bool identity_eq = e == elt;
if (identity_eq) if (identity_eq)
return True; return true;
int r = PyObject_RichCompareBool(e, elt, Py_EQ); int r = PyObject_RichCompareBool(e, elt, Py_EQ);
if (r == -1) if (r == -1)
throwCAPIException(); throwCAPIException();
if (r) if (r)
return True; return true;
} }
return False; return false;
}
static int list_contains(PyListObject* a, PyObject* el) {
return list_contains_shared((BoxedList*)a, el);
}
Box* listContains(BoxedList* self, Box* elt) {
return boxBool(list_contains_shared(self, elt));
} }
Box* listCount(BoxedList* self, Box* elt) { Box* listCount(BoxedList* self, Box* elt) {
...@@ -1195,9 +1240,13 @@ void setupList() { ...@@ -1195,9 +1240,13 @@ void setupList() {
list_cls->giveAttr("__hash__", None); list_cls->giveAttr("__hash__", None);
list_cls->freeze(); list_cls->freeze();
list_cls->tp_as_sequence->sq_slice = list_slice;
list_cls->tp_as_sequence->sq_length = list_length;
list_cls->tp_iter = listIter; list_cls->tp_iter = listIter;
list_cls->tp_as_sequence->sq_length = list_length;
list_cls->tp_as_sequence->sq_item = (ssizeargfunc)list_item;
list_cls->tp_as_sequence->sq_slice = list_slice;
list_cls->tp_as_sequence->sq_ass_item = (ssizeobjargproc)list_ass_item;
list_cls->tp_as_sequence->sq_ass_slice = (ssizessizeobjargproc)list_ass_slice;
list_cls->tp_as_sequence->sq_contains = (objobjproc)list_contains;
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1); CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL); addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL);
......
...@@ -1660,6 +1660,7 @@ static Box* str_slice(Box* o, Py_ssize_t i, Py_ssize_t j) { ...@@ -1660,6 +1660,7 @@ static Box* str_slice(Box* o, Py_ssize_t i, Py_ssize_t j) {
return PyString_FromStringAndSize(a->data() + i, j - i); return PyString_FromStringAndSize(a->data() + i, j - i);
} }
// Analoguous to CPython's, used for sq_ slots.
static Py_ssize_t str_length(Box* a) { static Py_ssize_t str_length(Box* a) {
return Py_SIZE(a); return Py_SIZE(a);
} }
...@@ -2062,14 +2063,14 @@ Box* strSwapcase(BoxedString* self) { ...@@ -2062,14 +2063,14 @@ Box* strSwapcase(BoxedString* self) {
return rtn; return rtn;
} }
Box* strContains(BoxedString* self, Box* elt) { static inline int string_contains_shared(BoxedString* self, Box* elt) {
assert(PyString_Check(self)); assert(PyString_Check(self));
if (PyUnicode_Check(elt)) { if (PyUnicode_Check(elt)) {
int r = PyUnicode_Contains(self, elt); int r = PyUnicode_Contains(self, elt);
if (r < 0) if (r < 0)
throwCAPIException(); throwCAPIException();
return boxBool(r); return r;
} }
if (!PyString_Check(elt)) if (!PyString_Check(elt))
...@@ -2083,9 +2084,16 @@ Box* strContains(BoxedString* self, Box* elt) { ...@@ -2083,9 +2084,16 @@ Box* strContains(BoxedString* self, Box* elt) {
found_idx = self->s().find(sub->s()[0]); found_idx = self->s().find(sub->s()[0]);
else else
found_idx = self->s().find(sub->s()); found_idx = self->s().find(sub->s());
if (found_idx == std::string::npos) return (found_idx != std::string::npos);
return False; }
return True;
// Analoguous to CPython's, used for sq_ slots.
static int string_contains(PyObject* str_obj, PyObject* sub_obj) {
return string_contains_shared((BoxedString*)str_obj, sub_obj);
}
Box* strContains(BoxedString* self, Box* elt) {
return boxBool(string_contains_shared(self, elt));
} }
// compares (a+a_pos, len) with (str) // compares (a+a_pos, len) with (str)
...@@ -2284,6 +2292,17 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) { ...@@ -2284,6 +2292,17 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) {
return result; return result;
} }
static PyObject* string_item(PyStringObject* self, register Py_ssize_t i) {
BoxedString* boxedString = (BoxedString*)self;
if (i < 0 || i >= boxedString->size()) {
raiseExcHelper(IndexError, "string index out of range");
}
char c = boxedString->s()[i];
return characters[c & UCHAR_MAX];
}
template <ExceptionStyle S> Box* strGetitem(BoxedString* self, Box* slice) { template <ExceptionStyle S> Box* strGetitem(BoxedString* self, Box* slice) {
if (S == CAPI) { if (S == CAPI) {
try { try {
...@@ -2857,10 +2876,12 @@ void setupStr() { ...@@ -2857,10 +2876,12 @@ void setupStr() {
add_operators(str_cls); add_operators(str_cls);
str_cls->freeze(); str_cls->freeze();
str_cls->tp_as_sequence->sq_slice = str_slice;
str_cls->tp_as_sequence->sq_length = str_length;
str_cls->tp_iter = (decltype(str_cls->tp_iter))strIter; str_cls->tp_iter = (decltype(str_cls->tp_iter))strIter;
str_cls->tp_hash = (hashfunc)str_hash; str_cls->tp_hash = (hashfunc)str_hash;
str_cls->tp_as_sequence->sq_length = str_length;
str_cls->tp_as_sequence->sq_item = (ssizeargfunc)string_item;
str_cls->tp_as_sequence->sq_slice = str_slice;
str_cls->tp_as_sequence->sq_contains = (objobjproc)string_contains;
basestring_cls->giveAttr("__doc__", basestring_cls->giveAttr("__doc__",
boxString("Type basestring cannot be instantiated; it is the base for str and unicode.")); boxString("Type basestring cannot be instantiated; it is the base for str and unicode."));
......
Subproject commit e1d16ce8922700ef6bde50589e84db3a5c095c2b Subproject commit 1b28a3b4c941c7b93fcc0c5174147641fdeadf30
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