Commit eae111dd authored by Kevin Modzelewski's avatar Kevin Modzelewski

Basic functools support

They do a refcount==1 optimization, where they mutate a tuple
if they see that it isn't shared.  I don't know if we can have
a good way of supporting this.

Maybe we can always tell extensions that refcounts are >1?  Not sure
if there's any macro magic we can do to make "obj->ob_refcnt" return
something of our choosing.
parent 2358b49b
......@@ -290,7 +290,7 @@ SRCS := $(MAIN_SRCS) $(STDLIB_SRCS)
STDLIB_OBJS := stdlib.bc.o stdlib.stripped.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 $(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 $(EXTRA_STDMODULE_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)
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)
add_custom_target(copy_stdlib ALL DEPENDS ${STDLIB_TARGETS})
# 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)
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)
# compile specified files in from_cpython/Objects
file(GLOB_RECURSE STDOBJECT_SRCS Objects structseq.c capsule.c stringobject.c)
......
......@@ -326,7 +326,7 @@ PyAPI_FUNC(void) PyObject_GC_Del(void *) PYSTON_NOEXCEPT;
#define _PyObject_GC_New _PyObject_New
#define PyObject_GC_Track(o) ((void)(o))
#define PyObject_GC_UnTrack(o) ((void)(o))
#define PyObject_GC_Del(o) ((void)(o))
#define PyObject_GC_Del PyObject_Del
#define PyObject_GC_New(type, typeobj) \
......
......@@ -35,7 +35,8 @@ functools_reduce(PyObject *self, PyObject *args)
for (;;) {
PyObject *op2;
if (args->ob_refcnt > 1) {
// Pyston change: can't do these sorts of refcount optimizations:
if (1 /*args->ob_refcnt > 1*/) {
Py_DECREF(args);
if ((args = PyTuple_New(2)) == NULL)
goto Fail;
......
......@@ -357,4 +357,115 @@ extern "C" int PyObject_IsSubclass(PyObject* derived, PyObject* cls) noexcept {
extern "C" PyObject* _PyObject_CallFunction_SizeT(PyObject* callable, char* format, ...) noexcept {
Py_FatalError("unimplemented");
}
#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->cls, Py_TPFLAGS_CHECKTYPES)
#define NB_SLOT(x) offsetof(PyNumberMethods, x)
#define NB_BINOP(nb_methods, slot) (*(binaryfunc*)(&((char*)nb_methods)[slot]))
#define NB_TERNOP(nb_methods, slot) (*(ternaryfunc*)(&((char*)nb_methods)[slot]))
extern "C" int PySequence_Check(PyObject* s) noexcept {
if (s == NULL)
return 0;
if (PyInstance_Check(s))
return PyObject_HasAttrString(s, "__getitem__");
if (PyDict_Check(s))
return 0;
return s->cls->tp_as_sequence && s->cls->tp_as_sequence->sq_item != NULL;
}
static PyObject* binary_op1(PyObject* v, PyObject* w, const int op_slot) {
PyObject* x;
binaryfunc slotv = NULL;
binaryfunc slotw = NULL;
if (v->cls->tp_as_number != NULL && NEW_STYLE_NUMBER(v))
slotv = NB_BINOP(v->cls->tp_as_number, op_slot);
if (w->cls != v->cls && w->cls->tp_as_number != NULL && NEW_STYLE_NUMBER(w)) {
slotw = NB_BINOP(w->cls->tp_as_number, op_slot);
if (slotw == slotv)
slotw = NULL;
}
if (slotv) {
if (slotw && PyType_IsSubtype(w->cls, v->cls)) {
x = slotw(v, w);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
slotw = NULL;
}
x = slotv(v, w);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
}
if (slotw) {
x = slotw(v, w);
if (x != Py_NotImplemented)
return x;
Py_DECREF(x); /* can't do it */
}
if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w)) {
int err = PyNumber_CoerceEx(&v, &w);
if (err < 0) {
return NULL;
}
if (err == 0) {
PyNumberMethods* mv = v->cls->tp_as_number;
if (mv) {
binaryfunc slot;
slot = NB_BINOP(mv, op_slot);
if (slot) {
x = slot(v, w);
Py_DECREF(v);
Py_DECREF(w);
return x;
}
}
/* CoerceEx incremented the reference counts */
Py_DECREF(v);
Py_DECREF(w);
}
}
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
static PyObject* binop_type_error(PyObject* v, PyObject* w, const char* op_name) {
PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %.100s: "
"'%.100s' and '%.100s'",
op_name, v->cls->tp_name, w->cls->tp_name);
return NULL;
}
static PyObject* binary_op(PyObject* v, PyObject* w, const int op_slot, const char* op_name) {
PyObject* result = binary_op1(v, w, op_slot);
if (result == Py_NotImplemented) {
Py_DECREF(result);
return binop_type_error(v, w, op_name);
}
return result;
}
extern "C" PyObject* PySequence_Concat(PyObject* s, PyObject* o) noexcept {
PySequenceMethods* m;
if (s == NULL || o == NULL)
return null_error();
m = s->cls->tp_as_sequence;
if (m && m->sq_concat)
return m->sq_concat(s, o);
/* Instances of user classes defining an __add__() method only
have an nb_add slot, not an sq_concat slot. So we fall back
to nb_add if both arguments appear to be sequences. */
if (PySequence_Check(s) && PySequence_Check(o)) {
PyObject* result = binary_op1(s, o, NB_SLOT(nb_add));
if (result != Py_NotImplemented)
return result;
Py_DECREF(result);
}
return type_error("'%.200s' object can't be concatenated", s);
}
}
......@@ -1697,7 +1697,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
RELEASE_ASSERT(cls->tp_iternext == NULL, "");
RELEASE_ASSERT(cls->tp_descr_get == NULL, "");
RELEASE_ASSERT(cls->tp_descr_set == NULL, "");
RELEASE_ASSERT(cls->tp_free == NULL || cls->tp_free == PyObject_Del, "");
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_mro == NULL, "");
RELEASE_ASSERT(cls->tp_cache == NULL, "");
......
......@@ -469,18 +469,10 @@ extern "C" int PyObject_Print(PyObject* obj, FILE* fp, int flags) noexcept {
Py_FatalError("unimplemented");
};
extern "C" int PySequence_Check(PyObject*) noexcept {
Py_FatalError("unimplemented");
}
extern "C" Py_ssize_t PySequence_Size(PyObject* o) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PySequence_Concat(PyObject* o1, PyObject* o2) noexcept {
Py_FatalError("unimplemented");
}
extern "C" PyObject* PySequence_Repeat(PyObject* o, Py_ssize_t count) noexcept {
Py_FatalError("unimplemented");
}
......
......@@ -132,6 +132,16 @@ extern "C" void PyDict_Clear(PyObject* op) noexcept {
static_cast<BoxedDict*>(op)->d.clear();
}
extern "C" PyObject* PyDict_Copy(PyObject* o) noexcept {
RELEASE_ASSERT(PyDict_Check(o), "");
try {
return dictCopy(static_cast<BoxedDict*>(o));
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
return NULL;
}
}
Box* dictGetitem(BoxedDict* self, Box* k) {
assert(self->cls == dict_cls);
......@@ -382,6 +392,24 @@ void dictMergeFromSeq2(BoxedDict* self, Box* other) {
}
}
extern "C" int PyDict_Merge(PyObject* a, PyObject* b, int override_) noexcept {
if (a == NULL || !PyDict_Check(a) || b == NULL) {
PyErr_BadInternalCall();
return -1;
}
if (override_ != 1)
Py_FatalError("unimplemented");
try {
dictMerge(static_cast<BoxedDict*>(a), b);
return 0;
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
return -1;
}
}
Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
assert(args->cls == tuple_cls);
assert(kwargs);
......
......@@ -49,6 +49,7 @@ extern "C" void initpwd();
extern "C" void initposix();
extern "C" void init_struct();
extern "C" void initdatetime();
extern "C" void init_functools();
namespace pyston {
......@@ -1143,6 +1144,7 @@ void setupRuntime() {
initposix();
init_struct();
initdatetime();
init_functools();
setupSysEnd();
......
import functools
f = functools.partial(lambda *args: args, 1, 23)
print f("hello")
print f("world", 5)
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