Commit 0d1017f8 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Centralize the PyType code into a new typeobject.cpp

parent 7096bf08
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "capi/typeobject.h"
#include "capi/types.h"
#include "runtime/objmodel.h"
namespace pyston {
// FIXME duplicated with objmodel.cpp
static const std::string _new_str("__new__");
PyObject* Py_CallPythonNew(PyTypeObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
// TODO: runtime ICs?
Box* new_attr = typeLookup(self, _new_str, NULL);
assert(new_attr);
new_attr = processDescriptor(new_attr, None, self);
return runtimeCall(new_attr, ArgPassSpec(1, 0, true, true), self, args, kwds, NULL, NULL);
} catch (Box* e) {
abort();
}
}
PyObject* Py_CallPythonCall(PyObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
// TODO: runtime ICs?
return runtimeCall(self, ArgPassSpec(0, 0, true, true), args, kwds, NULL, NULL, NULL);
} catch (Box* e) {
abort();
}
}
bool update_slot(BoxedClass* self, const std::string& attr) {
if (attr == "__new__") {
self->tp_new = &Py_CallPythonNew;
// TODO update subclasses
return true;
}
if (attr == "__call__") {
self->tp_call = &Py_CallPythonCall;
// TODO update subclasses
return true;
}
return false;
}
void fixup_slot_dispatchers(BoxedClass* self) {
// This will probably share a lot in common with Py_TypeReady:
if (!self->tp_new) {
self->tp_new = &Py_CallPythonNew;
} else if (self->tp_new != Py_CallPythonNew) {
ASSERT(0, "need to set __new__?");
}
if (!self->tp_call) {
self->tp_call = &Py_CallPythonCall;
} else if (self->tp_call != Py_CallPythonCall) {
ASSERT(0, "need to set __call__?");
}
}
} // namespace pyston
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_CAPI_TYPEOBJECT_H
#define PYSTON_CAPI_TYPEOBJECT_H
#include "runtime/types.h"
namespace pyston {
bool update_slot(BoxedClass* self, const std::string& attr);
void fixup_slot_dispatchers(BoxedClass* self);
}
#endif
......@@ -192,6 +192,17 @@ PyObject* tp_new_wrapper(PyTypeObject* self, BoxedTuple* args, Box* kwds) {
return self->tp_new(subtype, new_args, kwds);
}
static void add_operators(PyTypeObject* cls) {
if (cls->tp_new) {
cls->giveAttr("__new__",
new BoxedCApiFunction(METH_VARARGS | METH_KEYWORDS, cls, "__new__", (PyCFunction)tp_new_wrapper));
}
if (cls->tp_call) {
cls->giveAttr("__call__", new BoxedWrapperDescriptor(&call_wrapper, cls));
}
}
extern "C" int PyType_Ready(PyTypeObject* cls) {
gc::registerNonheapRootObject(cls);
......@@ -255,19 +266,12 @@ extern "C" int PyType_Ready(PyTypeObject* cls) {
if (!cls->tp_new && base != object_cls)
cls->tp_new = base->tp_new;
if (cls->tp_new) {
cls->giveAttr("__new__",
new BoxedCApiFunction(METH_VARARGS | METH_KEYWORDS, cls, "__new__", (PyCFunction)tp_new_wrapper));
}
if (cls->tp_call) {
cls->giveAttr("__call__", new BoxedWrapperDescriptor(&call_wrapper, cls));
}
if (!cls->tp_alloc) {
cls->tp_alloc = reinterpret_cast<decltype(cls->tp_alloc)>(PyType_GenericAlloc);
}
add_operators(cls);
for (PyMethodDef* method = cls->tp_methods; method && method->ml_name; ++method) {
cls->giveAttr(method->ml_name, new BoxedMethodDescriptor(method, cls));
}
......
......@@ -23,6 +23,7 @@
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "capi/typeobject.h"
#include "codegen/ast_interpreter.h"
#include "codegen/codegen.h"
#include "codegen/compvars.h"
......@@ -332,45 +333,11 @@ extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size) {
return &elts[0];
}
PyObject* Py_CallPythonNew(PyTypeObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
Box* new_attr = typeLookup(self, _new_str, NULL);
assert(new_attr);
new_attr = processDescriptor(new_attr, None, self);
return runtimeCallInternal(new_attr, NULL, ArgPassSpec(1, 0, true, true), self, args, kwds, NULL, NULL);
} catch (Box* e) {
abort();
}
}
PyObject* Py_CallPythonCall(PyObject* self, PyObject* args, PyObject* kwds) {
try {
Py_FatalError("this function is untested");
return runtimeCallInternal(self, NULL, ArgPassSpec(0, 0, true, true), args, kwds, NULL, NULL, NULL);
} catch (Box* e) {
abort();
}
}
void BoxedClass::freeze() {
assert(!is_constant);
assert(getattr("__name__")); // otherwise debugging will be very hard
// This will probably share a lot in common with Py_TypeReady:
if (!tp_new) {
this->tp_new = &Py_CallPythonNew;
} else if (tp_new != Py_CallPythonNew) {
ASSERT(0, "need to set __new__?");
}
if (!tp_call) {
this->tp_call = &Py_CallPythonCall;
} else if (tp_call != Py_CallPythonCall) {
ASSERT(0, "need to set __call__?");
}
fixup_slot_dispatchers(this);
is_constant = true;
}
......@@ -1485,19 +1452,9 @@ void setattrInternal(Box* obj, const std::string& attr, Box* val, SetattrRewrite
if (attr == "__base__" && self->getattr("__base__"))
raiseExcHelper(TypeError, "readonly attribute");
if (attr == "__new__") {
self->tp_new = &Py_CallPythonNew;
// TODO update subclasses
bool touched_slot = update_slot(self, attr);
if (touched_slot)
rewrite_args = NULL;
}
if (attr == "__call__") {
self->tp_call = &Py_CallPythonCall;
// TODO update subclasses
rewrite_args = NULL;
}
}
Box* _set_ = NULL;
......
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