Commit 681446ac authored by Kevin Modzelewski's avatar Kevin Modzelewski

Basic _collections support

Fixes #192
parent cb68b868
...@@ -290,7 +290,7 @@ SRCS := $(MAIN_SRCS) $(STDLIB_SRCS) ...@@ -290,7 +290,7 @@ SRCS := $(MAIN_SRCS) $(STDLIB_SRCS)
STDLIB_OBJS := stdlib.bc.o stdlib.stripped.bc.o STDLIB_OBJS := stdlib.bc.o stdlib.stripped.bc.o
STDLIB_RELEASE_OBJS := stdlib.release.bc.o STDLIB_RELEASE_OBJS := stdlib.release.bc.o
STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c $(EXTRA_STDMODULE_SRCS) STDMODULE_SRCS := errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c $(EXTRA_STDMODULE_SRCS)
STDOBJECT_SRCS := structseq.c capsule.c stringobject.c $(EXTRA_STDOBJECT_SRCS) STDOBJECT_SRCS := structseq.c capsule.c stringobject.c $(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := pyctype.c getargs.c formatter_string.c pystrtod.c dtoa.c $(EXTRA_STDPYTHON_SRCS) STDPYTHON_SRCS := pyctype.c getargs.c formatter_string.c pystrtod.c dtoa.c $(EXTRA_STDPYTHON_SRCS)
FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS)) FROM_CPYTHON_SRCS := $(addprefix from_cpython/Modules/,$(STDMODULE_SRCS)) $(addprefix from_cpython/Objects/,$(STDOBJECT_SRCS)) $(addprefix from_cpython/Python/,$(STDPYTHON_SRCS))
......
...@@ -15,7 +15,7 @@ endforeach(STDLIB_FILE) ...@@ -15,7 +15,7 @@ endforeach(STDLIB_FILE)
add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS}) add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS})
# compile specified files in from_cpython/Modules # compile specified files in from_cpython/Modules
file(GLOB_RECURSE STDMODULE_SRCS Modules errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c) file(GLOB_RECURSE STDMODULE_SRCS Modules errnomodule.c shamodule.c sha256module.c sha512module.c _math.c mathmodule.c md5.c md5module.c _randommodule.c _sre.c operator.c binascii.c pwdmodule.c posixmodule.c _struct.c datetimemodule.c _functoolsmodule.c _collectionsmodule.c)
# compile specified files in from_cpython/Objects # compile specified files in from_cpython/Objects
file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c) file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c)
......
...@@ -92,8 +92,10 @@ struct _dictobject { ...@@ -92,8 +92,10 @@ struct _dictobject {
PyDictEntry ma_smalltable[PyDict_MINSIZE]; PyDictEntry ma_smalltable[PyDict_MINSIZE];
}; };
#endif #endif
PyAPI_DATA(PyTypeObject*) list_cls; typedef struct {
#define PyList_Type (*list_cls) PyObject_HEAD;
char _filler[48];
} PyDictObject;
// Pyston change: these are no longer static objects: // Pyston change: these are no longer static objects:
#if 0 #if 0
......
...@@ -116,6 +116,8 @@ typedef struct _ts { ...@@ -116,6 +116,8 @@ typedef struct _ts {
PyObject *curexc_type; PyObject *curexc_type;
PyObject *curexc_value; PyObject *curexc_value;
PyObject *curexc_traceback; PyObject *curexc_traceback;
PyObject *dict; /* Stores per-thread state */
} PyThreadState; } PyThreadState;
......
...@@ -468,4 +468,28 @@ extern "C" PyObject* PySequence_Concat(PyObject* s, PyObject* o) noexcept { ...@@ -468,4 +468,28 @@ extern "C" PyObject* PySequence_Concat(PyObject* s, PyObject* o) noexcept {
} }
return type_error("'%.200s' object can't be concatenated", s); return type_error("'%.200s' object can't be concatenated", s);
} }
extern "C" PyObject* PySequence_List(PyObject* v) noexcept {
PyObject* result; /* result list */
PyObject* rv; /* return value from PyList_Extend */
if (v == NULL)
return null_error();
result = PyList_New(0);
if (result == NULL)
return NULL;
rv = _PyList_Extend((PyListObject*)result, v);
if (rv == NULL) {
Py_DECREF(result);
return NULL;
}
Py_DECREF(rv);
return result;
}
extern "C" PyObject* PyObject_CallFunction(PyObject* callable, char* format, ...) noexcept {
Py_FatalError("unimplemented");
}
} }
...@@ -128,4 +128,65 @@ extern "C" int PyObject_RichCompareBool(PyObject* v, PyObject* w, int op) noexce ...@@ -128,4 +128,65 @@ extern "C" int PyObject_RichCompareBool(PyObject* v, PyObject* w, int op) noexce
extern "C" PyObject** _PyObject_GetDictPtr(PyObject* obj) noexcept { extern "C" PyObject** _PyObject_GetDictPtr(PyObject* obj) noexcept {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
/* These methods are used to control infinite recursion in repr, str, print,
etc. Container objects that may recursively contain themselves,
e.g. builtin dictionaries and lists, should used Py_ReprEnter() and
Py_ReprLeave() to avoid infinite recursion.
Py_ReprEnter() returns 0 the first time it is called for a particular
object and 1 every time thereafter. It returns -1 if an exception
occurred. Py_ReprLeave() has no return value.
See dictobject.c and listobject.c for examples of use.
*/
#define KEY "Py_Repr"
extern "C" int Py_ReprEnter(PyObject* obj) noexcept {
PyObject* dict;
PyObject* list;
Py_ssize_t i;
dict = PyThreadState_GetDict();
if (dict == NULL)
return 0;
list = PyDict_GetItemString(dict, KEY);
if (list == NULL) {
list = PyList_New(0);
if (list == NULL)
return -1;
if (PyDict_SetItemString(dict, KEY, list) < 0)
return -1;
Py_DECREF(list);
}
i = PyList_GET_SIZE(list);
while (--i >= 0) {
if (PyList_GET_ITEM(list, i) == obj)
return 1;
}
PyList_Append(list, obj);
return 0;
}
extern "C" void Py_ReprLeave(PyObject* obj) noexcept {
PyObject* dict;
PyObject* list;
Py_ssize_t i;
dict = PyThreadState_GetDict();
if (dict == NULL)
return;
list = PyDict_GetItemString(dict, KEY);
if (list == NULL || !PyList_Check(list))
return;
i = PyList_GET_SIZE(list);
/* Count backwards because we always expect obj to be list[-1] */
while (--i >= 0) {
if (PyList_GET_ITEM(list, i) == obj) {
PyList_SetSlice(list, i, i + 1, NULL);
break;
}
}
}
} }
...@@ -1723,7 +1723,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -1723,7 +1723,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
gc::registerNonheapRootObject(cls); gc::registerNonheapRootObject(cls);
// unhandled fields: // unhandled fields:
RELEASE_ASSERT(cls->tp_print == NULL, "");
RELEASE_ASSERT(cls->tp_getattr == NULL, ""); RELEASE_ASSERT(cls->tp_getattr == NULL, "");
RELEASE_ASSERT(cls->tp_setattr == NULL, ""); RELEASE_ASSERT(cls->tp_setattr == NULL, "");
RELEASE_ASSERT(cls->tp_compare == NULL, ""); RELEASE_ASSERT(cls->tp_compare == NULL, "");
...@@ -1749,6 +1748,8 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -1749,6 +1748,8 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
RELEASE_ASSERT(cls->tp_del == NULL, ""); RELEASE_ASSERT(cls->tp_del == NULL, "");
RELEASE_ASSERT(cls->tp_version_tag == 0, ""); RELEASE_ASSERT(cls->tp_version_tag == 0, "");
// Pyston doesn't handle tp_print, but it looks like it's just for optimization so it should be ok to skip for now?
// I think it is safe to ignore these for for now: // I think it is safe to ignore these for for now:
// RELEASE_ASSERT(cls->tp_weaklistoffset == 0, ""); // RELEASE_ASSERT(cls->tp_weaklistoffset == 0, "");
// RELEASE_ASSERT(cls->tp_traverse == NULL, ""); // RELEASE_ASSERT(cls->tp_traverse == NULL, "");
......
...@@ -36,7 +36,7 @@ namespace threading { ...@@ -36,7 +36,7 @@ namespace threading {
extern "C" { extern "C" {
__thread PyThreadState cur_thread_state __thread PyThreadState cur_thread_state
= { 0, NULL, NULL, NULL }; // not sure if we need to explicitly request zero-initialization = { 0, NULL, NULL, NULL, NULL }; // not sure if we need to explicitly request zero-initialization
} }
PthreadFastMutex threading_lock; PthreadFastMutex threading_lock;
......
...@@ -531,10 +531,6 @@ extern "C" Py_ssize_t PySequence_Index(PyObject* o, PyObject* value) noexcept { ...@@ -531,10 +531,6 @@ extern "C" Py_ssize_t PySequence_Index(PyObject* o, PyObject* value) noexcept {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
extern "C" PyObject* PySequence_List(PyObject* o) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PySequence_Tuple(PyObject* o) noexcept { extern "C" PyObject* PySequence_Tuple(PyObject* o) noexcept {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
...@@ -1221,6 +1217,14 @@ static int dev_urandom_python(char* buffer, Py_ssize_t size) noexcept { ...@@ -1221,6 +1217,14 @@ static int dev_urandom_python(char* buffer, Py_ssize_t size) noexcept {
} }
} }
extern "C" PyObject* PyThreadState_GetDict(void) noexcept {
Box* dict = cur_thread_state.dict;
if (!dict) {
dict = cur_thread_state.dict = new BoxedDict();
}
return dict;
}
extern "C" int _PyOS_URandom(void* buffer, Py_ssize_t size) noexcept { extern "C" int _PyOS_URandom(void* buffer, Py_ssize_t size) noexcept {
if (size < 0) { if (size < 0) {
PyErr_Format(PyExc_ValueError, "negative argument not allowed"); PyErr_Format(PyExc_ValueError, "negative argument not allowed");
......
...@@ -341,20 +341,26 @@ Box* listMul(BoxedList* self, Box* rhs) { ...@@ -341,20 +341,26 @@ Box* listMul(BoxedList* self, Box* rhs) {
} }
Box* listIAdd(BoxedList* self, Box* _rhs) { Box* listIAdd(BoxedList* self, Box* _rhs) {
if (_rhs->cls != list_cls) {
raiseExcHelper(TypeError, "can only concatenate list (not \"%s\") to list", getTypeName(_rhs)->c_str());
}
LOCK_REGION(self->lock.asWrite()); LOCK_REGION(self->lock.asWrite());
BoxedList* rhs = static_cast<BoxedList*>(_rhs); if (_rhs->cls == list_cls) {
// This branch is safe if self==rhs:
BoxedList* rhs = static_cast<BoxedList*>(_rhs);
int s1 = self->size; int s1 = self->size;
int s2 = rhs->size; int s2 = rhs->size;
self->ensure(s1 + s2); self->ensure(s1 + s2);
memcpy(self->elts->elts + s1, rhs->elts->elts, sizeof(rhs->elts->elts[0]) * s2);
self->size = s1 + s2;
return self;
}
RELEASE_ASSERT(_rhs != self, "unsupported");
for (auto* b : _rhs->pyElements())
listAppendInternal(self, b);
memcpy(self->elts->elts + s1, rhs->elts->elts, sizeof(rhs->elts->elts[0]) * s2);
self->size = s1 + s2;
return self; return self;
} }
...@@ -578,6 +584,39 @@ Box* listNe(BoxedList* self, Box* rhs) { ...@@ -578,6 +584,39 @@ Box* listNe(BoxedList* self, Box* rhs) {
return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::NotEq); return _listCmp(self, static_cast<BoxedList*>(rhs), AST_TYPE::NotEq);
} }
extern "C" PyObject* _PyList_Extend(PyListObject* self, PyObject* b) noexcept {
BoxedList* l = (BoxedList*)self;
assert(l->cls == list_cls);
try {
return listIAdd(l, b);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
return NULL;
}
}
extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject* v) noexcept {
if (!PyList_Check(a)) {
PyErr_BadInternalCall();
return -1;
}
BoxedList* l = (BoxedList*)a;
ASSERT(l->cls == list_cls, "%s", l->cls->tp_name);
try {
if (v)
listSetitemSlice(l, new BoxedSlice(boxInt(ilow), boxInt(ihigh), None), v);
else
listDelitemSlice(l, new BoxedSlice(boxInt(ilow), boxInt(ihigh), None));
return 0;
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
return -1;
}
}
void setupList() { void setupList() {
list_iterator_cls = new BoxedHeapClass(object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false); list_iterator_cls = new BoxedHeapClass(object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false);
......
...@@ -50,6 +50,7 @@ extern "C" void initposix(); ...@@ -50,6 +50,7 @@ extern "C" void initposix();
extern "C" void init_struct(); extern "C" void init_struct();
extern "C" void initdatetime(); extern "C" void initdatetime();
extern "C" void init_functools(); extern "C" void init_functools();
extern "C" void init_collections();
namespace pyston { namespace pyston {
...@@ -1145,6 +1146,7 @@ void setupRuntime() { ...@@ -1145,6 +1146,7 @@ void setupRuntime() {
init_struct(); init_struct();
initdatetime(); initdatetime();
init_functools(); init_functools();
init_collections();
setupSysEnd(); setupSysEnd();
......
...@@ -431,6 +431,7 @@ public: ...@@ -431,6 +431,7 @@ public:
return NULL; return NULL;
} }
}; };
static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), "");
class BoxedFunction : public Box { class BoxedFunction : public Box {
public: public:
......
import _collections
d = _collections.deque()
print d
d.append(1)
d.appendleft(2)
d.append(3)
print d
print
print type(iter(d))
for i in d:
print i
while d:
print d.popleft()
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