Commit 75e203a2 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #768 from kmod/exceptions2

start templatizing the runtime to be able to choose exception styles
parents 52a94c1d 8170d8ae
...@@ -732,12 +732,10 @@ exit: ...@@ -732,12 +732,10 @@ exit:
} }
extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept { extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept {
try { BoxedInt* r = lenInternal<ExceptionStyle::CAPI>(o, NULL);
return len(o)->n; if (!r)
} catch (ExcInfo e) {
setCAPIException(e);
return -1; return -1;
} return r->n;
} }
extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept { extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept {
......
...@@ -534,7 +534,7 @@ extern "C" int PyObject_SetAttrString(PyObject* v, const char* name, PyObject* w ...@@ -534,7 +534,7 @@ extern "C" int PyObject_SetAttrString(PyObject* v, const char* name, PyObject* w
extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexcept { extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexcept {
try { try {
Box* r = getattrInternal(o, internStringMortal(attr), NULL); Box* r = getattrInternal<ExceptionStyle::CXX>(o, internStringMortal(attr), NULL);
if (!r) if (!r)
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name, attr); PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name, attr);
return r; return r;
......
...@@ -532,8 +532,14 @@ static PyObject* lookup_maybe(PyObject* self, const char* attrstr, PyObject** at ...@@ -532,8 +532,14 @@ static PyObject* lookup_maybe(PyObject* self, const char* attrstr, PyObject** at
} }
Box* obj = typeLookup(self->cls, (BoxedString*)*attrobj, NULL); Box* obj = typeLookup(self->cls, (BoxedString*)*attrobj, NULL);
if (obj) if (obj) {
return processDescriptor(obj, self, self->cls); try {
return processDescriptor(obj, self, self->cls);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
return obj; return obj;
} }
......
...@@ -68,6 +68,13 @@ enum class EffortLevel { ...@@ -68,6 +68,13 @@ enum class EffortLevel {
MAXIMAL = 3, MAXIMAL = 3,
}; };
namespace ExceptionStyle {
enum ExceptionStyle {
CAPI,
CXX,
};
};
class CompilerType; class CompilerType;
template <class V> class ValuedCompilerType; template <class V> class ValuedCompilerType;
typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType; typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType;
......
...@@ -452,24 +452,14 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) { ...@@ -452,24 +452,14 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
raiseExcHelper(TypeError, "getattr(): attribute name must be string"); raiseExcHelper(TypeError, "getattr(): attribute name must be string");
} }
BoxedString* str = static_cast<BoxedString*>(_str); Box* rtn = PyObject_GetAttr(obj, _str);
internStringMortalInplace(str); if (rtn == NULL && default_value != NULL && PyErr_ExceptionMatches(AttributeError)) {
PyErr_Clear();
Box* rtn = NULL; return default_value;
try {
rtn = getattrInternal(obj, str, NULL);
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
throw e;
}
if (!rtn) {
if (default_value)
return default_value;
else
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", getTypeName(obj), str->data());
} }
if (!rtn)
throwCAPIException();
return rtn; return rtn;
} }
...@@ -499,7 +489,7 @@ Box* hasattr(Box* obj, Box* _str) { ...@@ -499,7 +489,7 @@ Box* hasattr(Box* obj, Box* _str) {
Box* attr; Box* attr;
try { try {
attr = getattrInternal(obj, str, NULL); attr = getattrInternal<ExceptionStyle::CXX>(obj, str, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (e.matches(Exception)) if (e.matches(Exception))
return False; return False;
......
...@@ -204,13 +204,29 @@ done: ...@@ -204,13 +204,29 @@ done:
} }
extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept { extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr) noexcept {
try { if (!PyString_Check(attr)) {
return getattrMaybeNonstring(o, attr_name); if (PyUnicode_Check(attr)) {
} catch (ExcInfo e) { attr = _PyUnicode_AsDefaultEncodedString(attr, NULL);
setCAPIException(e); if (attr == NULL)
return NULL; return NULL;
} else {
PyErr_Format(TypeError, "attribute name must be string, not '%.200s'", Py_TYPE(attr)->tp_name);
return NULL;
}
} }
BoxedString* s = static_cast<BoxedString*>(attr);
internStringMortalInplace(s);
Box* r = getattrInternal<ExceptionStyle::CAPI>(o, s, NULL);
if (!r && !PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name,
PyString_AS_STRING(attr));
}
return r;
} }
extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexcept { extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexcept {
...@@ -441,12 +457,7 @@ done: ...@@ -441,12 +457,7 @@ done:
extern "C" PyObject* PyObject_GetItem(PyObject* o, PyObject* key) noexcept { extern "C" PyObject* PyObject_GetItem(PyObject* o, PyObject* key) noexcept {
try { return getitemInternal<ExceptionStyle::CAPI>(o, key, NULL);
return getitem(o, key);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} }
extern "C" int PyObject_SetItem(PyObject* o, PyObject* key, PyObject* v) noexcept { extern "C" int PyObject_SetItem(PyObject* o, PyObject* key, PyObject* v) noexcept {
......
...@@ -46,7 +46,7 @@ static void propertyDocCopy(BoxedProperty* prop, Box* fget) { ...@@ -46,7 +46,7 @@ static void propertyDocCopy(BoxedProperty* prop, Box* fget) {
static BoxedString* doc_str = internStringImmortal("__doc__"); static BoxedString* doc_str = internStringImmortal("__doc__");
try { try {
get_doc = getattrInternal(fget, doc_str, NULL); get_doc = getattrInternal<ExceptionStyle::CXX>(fget, doc_str, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(Exception)) { if (!e.matches(Exception)) {
throw e; throw e;
......
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
namespace pyston { namespace pyston {
using namespace pyston::ExceptionStyle;
using pyston::ExceptionStyle::ExceptionStyle;
Box* dictRepr(BoxedDict* self) { Box* dictRepr(BoxedDict* self) {
std::vector<char> chars; std::vector<char> chars;
chars.push_back('{'); chars.push_back('{');
...@@ -183,23 +186,54 @@ extern "C" int PyDict_Update(PyObject* a, PyObject* b) noexcept { ...@@ -183,23 +186,54 @@ extern "C" int PyDict_Update(PyObject* a, PyObject* b) noexcept {
return PyDict_Merge(a, b, 1); return PyDict_Merge(a, b, 1);
} }
Box* dictGetitem(BoxedDict* self, Box* k) { template <enum ExceptionStyle S> Box* dictGetitem(BoxedDict* self, Box* k) noexcept(S == CAPI) {
if (!isSubclass(self->cls, dict_cls)) if (!isSubclass(self->cls, dict_cls)) {
raiseExcHelper(TypeError, "descriptor '__getitem__' requires a 'dict' object but received a '%s'", if (S == CAPI) {
getTypeName(self)); PyErr_Format(TypeError, "descriptor '__getitem__' requires a 'dict' object but received a '%s'",
getTypeName(self));
return NULL;
} else {
raiseExcHelper(TypeError, "descriptor '__getitem__' requires a 'dict' object but received a '%s'",
getTypeName(self));
}
}
BoxedDict::DictMap::iterator it;
try {
it = self->d.find(k);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else {
throw e;
}
}
auto it = self->d.find(k);
if (it == self->d.end()) { if (it == self->d.end()) {
// Try calling __missing__ if this is a subclass // Try calling __missing__ if this is a subclass
if (self->cls != dict_cls) { if (self->cls != dict_cls) {
static BoxedString* missing_str = internStringImmortal("__missing__"); static BoxedString* missing_str = internStringImmortal("__missing__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(1) }; CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(1) };
Box* r = callattr(self, missing_str, callattr_flags, k, NULL, NULL, NULL, NULL); Box* r;
try {
r = callattr(self, missing_str, callattr_flags, k, NULL, NULL, NULL, NULL);
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else
throw e;
}
if (r) if (r)
return r; return r;
} }
raiseExcHelper(KeyError, k); if (S == CAPI) {
PyErr_SetObject(KeyError, k);
return NULL;
} else
raiseExcHelper(KeyError, k);
} }
return it->second; return it->second;
} }
...@@ -588,7 +622,7 @@ Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) { ...@@ -588,7 +622,7 @@ Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
if (args->size()) { if (args->size()) {
Box* arg = args->elts[0]; Box* arg = args->elts[0];
static BoxedString* keys_str = internStringImmortal("keys"); static BoxedString* keys_str = internStringImmortal("keys");
if (getattrInternal(arg, keys_str, NULL)) { if (getattrInternal<ExceptionStyle::CXX>(arg, keys_str, NULL)) {
dictMerge(self, arg); dictMerge(self, arg);
} else { } else {
dictMergeFromSeq2(self, arg); dictMergeFromSeq2(self, arg);
...@@ -715,7 +749,7 @@ void setupDict() { ...@@ -715,7 +749,7 @@ void setupDict() {
dict_cls->giveAttr("setdefault", dict_cls->giveAttr("setdefault",
new BoxedFunction(boxRTFunction((void*)dictSetdefault, UNKNOWN, 3, 1, false, false), { None })); new BoxedFunction(boxRTFunction((void*)dictSetdefault, UNKNOWN, 3, 1, false, false), { None }));
dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, UNKNOWN, 2))); dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem<CXX>, UNKNOWN, 2)));
dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NONE, 3))); dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NONE, 3)));
dict_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)dictDelitem, UNKNOWN, 2))); dict_cls->giveAttr("__delitem__", new BoxedFunction(boxRTFunction((void*)dictDelitem, UNKNOWN, 2)));
dict_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)dictContains, BOXED_BOOL, 2))); dict_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)dictContains, BOXED_BOOL, 2)));
...@@ -747,6 +781,8 @@ void setupDict() { ...@@ -747,6 +781,8 @@ 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_subscript = (binaryfunc)dictGetitem<CAPI>;
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)));
dict_keys_cls->freeze(); dict_keys_cls->freeze();
......
...@@ -382,7 +382,7 @@ static Box* importSub(const std::string& name, const std::string& full_name, Box ...@@ -382,7 +382,7 @@ static Box* importSub(const std::string& name, const std::string& full_name, Box
path_list = NULL; path_list = NULL;
} else { } else {
static BoxedString* path_str = internStringImmortal("__path__"); static BoxedString* path_str = internStringImmortal("__path__");
path_list = static_cast<BoxedList*>(getattrInternal(parent_module, path_str, NULL)); path_list = static_cast<BoxedList*>(getattrInternal<ExceptionStyle::CXX>(parent_module, path_str, NULL));
if (path_list == NULL || path_list->cls != list_cls) { if (path_list == NULL || path_list->cls != list_cls) {
return None; return None;
} }
...@@ -562,7 +562,7 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re ...@@ -562,7 +562,7 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re
static BoxedString* path_str = internStringImmortal("__path__"); static BoxedString* path_str = internStringImmortal("__path__");
Box* pathlist = NULL; Box* pathlist = NULL;
try { try {
pathlist = getattrInternal(module, path_str, NULL); pathlist = getattrInternal<ExceptionStyle::CXX>(module, path_str, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(AttributeError)) if (!e.matches(AttributeError))
throw e; throw e;
...@@ -584,14 +584,14 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re ...@@ -584,14 +584,14 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re
continue; continue;
static BoxedString* all_str = internStringImmortal("__all__"); static BoxedString* all_str = internStringImmortal("__all__");
Box* all = getattrInternal(module, all_str, NULL); Box* all = getattrInternal<ExceptionStyle::CXX>(module, all_str, NULL);
if (all) { if (all) {
ensureFromlist(module, all, buf, true); ensureFromlist(module, all, buf, true);
} }
continue; continue;
} }
Box* attr = getattrInternal(module, s, NULL); Box* attr = getattrInternal<ExceptionStyle::CXX>(module, s, NULL);
if (attr != NULL) if (attr != NULL)
continue; continue;
......
...@@ -49,42 +49,24 @@ bool seqiterHasnextUnboxed(Box* s) { ...@@ -49,42 +49,24 @@ bool seqiterHasnextUnboxed(Box* s) {
return false; return false;
} }
Box* next; Box* next = getitemInternal<ExceptionStyle::CAPI>(self->b, boxInt(self->idx), NULL);
try { if (!next) {
next = getitem(self->b, boxInt(self->idx)); if (PyErr_ExceptionMatches(IndexError) || PyErr_ExceptionMatches(StopIteration)) {
} catch (ExcInfo e) { PyErr_Clear();
if (e.matches(IndexError) || e.matches(StopIteration)) {
self->b = NULL; self->b = NULL;
return false; return false;
} else } else {
throw e; throwCAPIException();
}
} }
self->idx++; self->idx++;
self->next = next; self->next = next;
return true; return true;
} }
Box* seqiterHasnext(Box* s) { Box* seqiterHasnext(Box* s) {
RELEASE_ASSERT(s->cls == seqiter_cls || s->cls == seqreviter_cls, ""); return boxBool(seqiterHasnextUnboxed(s));
BoxedSeqIter* self = static_cast<BoxedSeqIter*>(s);
if (!self->b) {
return False;
}
Box* next;
try {
next = getitem(self->b, boxInt(self->idx));
} catch (ExcInfo e) {
if (e.matches(IndexError) || e.matches(StopIteration)) {
self->b = NULL;
return False;
} else
throw e;
}
self->idx++;
self->next = next;
return True;
} }
Box* seqreviterHasnext(Box* s) { Box* seqreviterHasnext(Box* s) {
......
...@@ -59,6 +59,9 @@ ...@@ -59,6 +59,9 @@
namespace pyston { namespace pyston {
using namespace pyston::ExceptionStyle;
using pyston::ExceptionStyle::ExceptionStyle;
static const std::string delitem_str("__delitem__"); static const std::string delitem_str("__delitem__");
static const std::string getattribute_str("__getattribute__"); static const std::string getattribute_str("__getattribute__");
static const std::string getattr_str("__getattr__"); static const std::string getattr_str("__getattr__");
...@@ -196,7 +199,7 @@ extern "C" bool softspace(Box* b, bool newval) { ...@@ -196,7 +199,7 @@ extern "C" bool softspace(Box* b, bool newval) {
bool r; bool r;
Box* gotten = NULL; Box* gotten = NULL;
try { try {
Box* gotten = getattrInternal(b, softspace_str, NULL); Box* gotten = getattrInternal<CXX>(b, softspace_str, NULL);
if (!gotten) { if (!gotten) {
r = 0; r = 0;
} else { } else {
...@@ -1470,10 +1473,16 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedS ...@@ -1470,10 +1473,16 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedS
return NULL; return NULL;
} }
template <enum ExceptionStyle S>
Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool cls_only, bool for_call, Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool cls_only, bool for_call,
Box** bind_obj_out, RewriterVar** r_bind_obj_out) { Box** bind_obj_out, RewriterVar** r_bind_obj_out) noexcept(S == ExceptionStyle::CAPI) {
assert(gc::isValidGCObject(attr)); assert(gc::isValidGCObject(attr));
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
if (!cls_only) { if (!cls_only) {
BoxedClass* cls = obj->cls; BoxedClass* cls = obj->cls;
...@@ -1486,10 +1495,20 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_ ...@@ -1486,10 +1495,20 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_
STAT_TIMER(t0, "us_timer_slowpath_tpgetattro", 10); STAT_TIMER(t0, "us_timer_slowpath_tpgetattro", 10);
if (obj->cls->tp_getattro == slot_tp_getattr_hook) { if (obj->cls->tp_getattro == slot_tp_getattr_hook) {
return slotTpGetattrHookInternal(obj, attr, rewrite_args); if (S == CAPI) {
assert(!rewrite_args && "implement me");
return obj->cls->tp_getattro(obj, attr);
} else {
return slotTpGetattrHookInternal(obj, attr, rewrite_args);
}
} }
Box* r = obj->cls->tp_getattro(obj, attr); Box* r = obj->cls->tp_getattro(obj, attr);
if (S == CAPI) {
assert(!rewrite_args && "implement me");
return r;
}
if (!r) if (!r)
throwCAPIException(); throwCAPIException();
...@@ -1517,20 +1536,35 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_ ...@@ -1517,20 +1536,35 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_
STAT_TIMER(t0, "us_timer_slowpath_tpgetattr", 10); STAT_TIMER(t0, "us_timer_slowpath_tpgetattr", 10);
assert(attr->data()[attr->size()] == '\0'); assert(attr->data()[attr->size()] == '\0');
Box* r = obj->cls->tp_getattr(obj, const_cast<char*>(attr->data())); Box* r = obj->cls->tp_getattr(obj, const_cast<char*>(attr->data()));
if (!r)
throwCAPIException(); if (S == CAPI) {
return r; return r;
} else {
if (!r)
throwCAPIException();
return r;
}
} }
} }
return getattrInternalGeneric(obj, attr, rewrite_args, cls_only, for_call, bind_obj_out, r_bind_obj_out); if (S == CAPI) {
try {
return getattrInternalGeneric(obj, attr, rewrite_args, cls_only, for_call, bind_obj_out, r_bind_obj_out);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} else {
return getattrInternalGeneric(obj, attr, rewrite_args, cls_only, for_call, bind_obj_out, r_bind_obj_out);
}
} }
inline Box* getclsattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) { inline Box* getclsattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) {
return getattrInternalEx(obj, attr, rewrite_args, return getattrInternalEx<CXX>(obj, attr, rewrite_args,
/* cls_only */ true, /* cls_only */ true,
/* for_call */ false, NULL, NULL); /* for_call */ false, NULL, NULL);
} }
extern "C" Box* getclsattr(Box* obj, BoxedString* attr) { extern "C" Box* getclsattr(Box* obj, BoxedString* attr) {
...@@ -1935,8 +1969,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1935,8 +1969,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
// TODO this shouldn't go here; it should be in instancemethod_cls->tp_getattr[o] // TODO this shouldn't go here; it should be in instancemethod_cls->tp_getattr[o]
if (obj->cls == instancemethod_cls) { if (obj->cls == instancemethod_cls) {
assert(!rewrite_args || !rewrite_args->out_success); assert(!rewrite_args || !rewrite_args->out_success);
return getattrInternalEx(static_cast<BoxedInstanceMethod*>(obj)->func, attr, NULL, cls_only, for_call, return getattrInternalEx<CXX>(static_cast<BoxedInstanceMethod*>(obj)->func, attr, NULL, cls_only, for_call,
bind_obj_out, NULL); bind_obj_out, NULL);
} }
if (rewrite_args) { if (rewrite_args) {
...@@ -1945,12 +1979,18 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1945,12 +1979,18 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
return NULL; return NULL;
} }
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) { template <enum ExceptionStyle S>
return getattrInternalEx(obj, attr, rewrite_args, Box* getattrInternal(Box* obj, BoxedString* attr,
/* cls_only */ false, GetattrRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI) {
/* for_call */ false, NULL, NULL); return getattrInternalEx<S>(obj, attr, rewrite_args,
/* cls_only */ false,
/* for_call */ false, NULL, NULL);
} }
// Force instantiation of the template
template Box* getattrInternal<CAPI>(Box*, BoxedString*, GetattrRewriteArgs*);
template Box* getattrInternal<CXX>(Box*, BoxedString*, GetattrRewriteArgs*);
Box* getattrMaybeNonstring(Box* obj, Box* attr) { Box* getattrMaybeNonstring(Box* obj, Box* attr) {
if (!PyString_Check(attr)) { if (!PyString_Check(attr)) {
if (PyUnicode_Check(attr)) { if (PyUnicode_Check(attr)) {
...@@ -1964,7 +2004,11 @@ Box* getattrMaybeNonstring(Box* obj, Box* attr) { ...@@ -1964,7 +2004,11 @@ Box* getattrMaybeNonstring(Box* obj, Box* attr) {
BoxedString* s = static_cast<BoxedString*>(attr); BoxedString* s = static_cast<BoxedString*>(attr);
internStringMortalInplace(s); internStringMortalInplace(s);
return getattr(obj, s);
Box* r = getattrInternal<CXX>(obj, s, NULL);
if (!r)
raiseAttributeError(obj, s->s());
return r;
} }
extern "C" Box* getattr(Box* obj, BoxedString* attr) { extern "C" Box* getattr(Box* obj, BoxedString* attr) {
...@@ -2018,7 +2062,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) { ...@@ -2018,7 +2062,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) {
else else
dest = rewriter->getReturnDestination(); dest = rewriter->getReturnDestination();
GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), dest); GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), dest);
val = getattrInternal(obj, attr, &rewrite_args); val = getattrInternal<CXX>(obj, attr, &rewrite_args);
if (rewrite_args.out_success) { if (rewrite_args.out_success) {
if (!val) { if (!val) {
...@@ -2040,7 +2084,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) { ...@@ -2040,7 +2084,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) {
} }
} }
} else { } else {
val = getattrInternal(obj, attr, NULL); val = getattrInternal<CXX>(obj, attr, NULL);
} }
if (val) { if (val) {
...@@ -2550,13 +2594,21 @@ extern "C" BoxedInt* hash(Box* obj) { ...@@ -2550,13 +2594,21 @@ extern "C" BoxedInt* hash(Box* obj) {
return new BoxedInt(r); return new BoxedInt(r);
} }
extern "C" BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) { template <enum ExceptionStyle S>
BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI) {
static BoxedString* len_str = internStringImmortal("__len__"); static BoxedString* len_str = internStringImmortal("__len__");
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
// Corresponds to the first part of PyObject_Size: // Corresponds to the first part of PyObject_Size:
PySequenceMethods* m = obj->cls->tp_as_sequence; PySequenceMethods* m = obj->cls->tp_as_sequence;
if (m != NULL && m->sq_length != NULL && m->sq_length != slot_sq_length) { if (m != NULL && m->sq_length != NULL && m->sq_length != slot_sq_length) {
if (rewrite_args) { if (rewrite_args) {
assert(S == CXX);
RewriterVar* r_obj = rewrite_args->obj; RewriterVar* r_obj = rewrite_args->obj;
RewriterVar* r_cls = r_obj->getAttr(offsetof(Box, cls)); RewriterVar* r_cls = r_obj->getAttr(offsetof(Box, cls));
RewriterVar* r_m = r_cls->getAttr(offsetof(BoxedClass, tp_as_sequence)); RewriterVar* r_m = r_cls->getAttr(offsetof(BoxedClass, tp_as_sequence));
...@@ -2577,29 +2629,50 @@ extern "C" BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) { ...@@ -2577,29 +2629,50 @@ extern "C" BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) {
} }
int r = (*m->sq_length)(obj); int r = (*m->sq_length)(obj);
if (r == -1) if (r == -1) {
throwCAPIException(); if (S == CAPI)
return NULL;
else
throwCAPIException();
}
return (BoxedInt*)boxInt(r); return (BoxedInt*)boxInt(r);
} }
Box* rtn; Box* rtn;
if (rewrite_args) { try {
CallRewriteArgs crewrite_args(rewrite_args->rewriter, rewrite_args->obj, rewrite_args->destination); if (rewrite_args) {
rtn = callattrInternal0(obj, len_str, CLASS_ONLY, &crewrite_args, ArgPassSpec(0)); CallRewriteArgs crewrite_args(rewrite_args->rewriter, rewrite_args->obj, rewrite_args->destination);
if (!crewrite_args.out_success) rtn = callattrInternal0(obj, len_str, CLASS_ONLY, &crewrite_args, ArgPassSpec(0));
rewrite_args = NULL; if (!crewrite_args.out_success)
else if (rtn) rewrite_args = NULL;
rewrite_args->out_rtn = crewrite_args.out_rtn; else if (rtn)
} else { rewrite_args->out_rtn = crewrite_args.out_rtn;
rtn = callattrInternal0(obj, len_str, CLASS_ONLY, NULL, ArgPassSpec(0)); } else {
rtn = callattrInternal0(obj, len_str, CLASS_ONLY, NULL, ArgPassSpec(0));
}
} catch (ExcInfo e) {
if (S == CAPI) {
setCAPIException(e);
return NULL;
} else {
throw e;
}
} }
if (rtn == NULL) { if (rtn == NULL) {
raiseExcHelper(TypeError, "object of type '%s' has no len()", getTypeName(obj)); if (S == CAPI) {
PyErr_Format(TypeError, "object of type '%s' has no len()", getTypeName(obj));
return NULL;
} else
raiseExcHelper(TypeError, "object of type '%s' has no len()", getTypeName(obj));
} }
if (rtn->cls != int_cls) { if (rtn->cls != int_cls) {
raiseExcHelper(TypeError, "an integer is required"); if (S == CAPI) {
PyErr_Format(TypeError, "an integer is required");
return NULL;
} else
raiseExcHelper(TypeError, "an integer is required");
} }
if (rewrite_args) if (rewrite_args)
...@@ -2607,6 +2680,10 @@ extern "C" BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) { ...@@ -2607,6 +2680,10 @@ extern "C" BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) {
return static_cast<BoxedInt*>(rtn); return static_cast<BoxedInt*>(rtn);
} }
// force template instantiation:
template BoxedInt* lenInternal<CAPI>(Box*, LenRewriteArgs*);
template BoxedInt* lenInternal<CXX>(Box*, LenRewriteArgs*);
Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) {
if (argspec != ArgPassSpec(1)) if (argspec != ArgPassSpec(1))
...@@ -2614,7 +2691,7 @@ Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, Arg ...@@ -2614,7 +2691,7 @@ Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, Arg
if (rewrite_args) { if (rewrite_args) {
LenRewriteArgs lrewrite_args(rewrite_args->rewriter, rewrite_args->arg1, rewrite_args->destination); LenRewriteArgs lrewrite_args(rewrite_args->rewriter, rewrite_args->arg1, rewrite_args->destination);
Box* rtn = lenInternal(arg1, &lrewrite_args); Box* rtn = lenInternal<CXX>(arg1, &lrewrite_args);
if (!lrewrite_args.out_success) { if (!lrewrite_args.out_success) {
rewrite_args = 0; rewrite_args = 0;
} else { } else {
...@@ -2623,7 +2700,7 @@ Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, Arg ...@@ -2623,7 +2700,7 @@ Box* lenCallInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, Arg
} }
return rtn; return rtn;
} }
return lenInternal(arg1, NULL); return lenInternal<CXX>(arg1, NULL);
} }
extern "C" BoxedInt* len(Box* obj) { extern "C" BoxedInt* len(Box* obj) {
...@@ -2632,7 +2709,7 @@ extern "C" BoxedInt* len(Box* obj) { ...@@ -2632,7 +2709,7 @@ extern "C" BoxedInt* len(Box* obj) {
static StatCounter slowpath_len("slowpath_len"); static StatCounter slowpath_len("slowpath_len");
slowpath_len.log(); slowpath_len.log();
return lenInternal(obj, NULL); return lenInternal<CXX>(obj, NULL);
} }
extern "C" i64 unboxedLen(Box* obj) { extern "C" i64 unboxedLen(Box* obj) {
...@@ -2649,14 +2726,14 @@ extern "C" i64 unboxedLen(Box* obj) { ...@@ -2649,14 +2726,14 @@ extern "C" i64 unboxedLen(Box* obj) {
if (rewriter.get()) { if (rewriter.get()) {
// rewriter->trap(); // rewriter->trap();
LenRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getReturnDestination()); LenRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getReturnDestination());
lobj = lenInternal(obj, &rewrite_args); lobj = lenInternal<CXX>(obj, &rewrite_args);
if (!rewrite_args.out_success) { if (!rewrite_args.out_success) {
rewriter.reset(NULL); rewriter.reset(NULL);
} else } else
r_boxed = rewrite_args.out_rtn; r_boxed = rewrite_args.out_rtn;
} else { } else {
lobj = lenInternal(obj, NULL); lobj = lenInternal<CXX>(obj, NULL);
} }
assert(lobj->cls == int_cls); assert(lobj->cls == int_cls);
...@@ -2885,14 +2962,14 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, ...@@ -2885,14 +2962,14 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope,
RewriterVar* r_val = NULL; RewriterVar* r_val = NULL;
if (rewrite_args) { if (rewrite_args) {
GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, Location::any()); GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, Location::any());
val = getattrInternalEx(obj, attr, &grewrite_args, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj); val = getattrInternalEx<CXX>(obj, attr, &grewrite_args, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj);
if (!grewrite_args.out_success) { if (!grewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
} else if (val) { } else if (val) {
r_val = grewrite_args.out_rtn; r_val = grewrite_args.out_rtn;
} }
} else { } else {
val = getattrInternalEx(obj, attr, NULL, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj); val = getattrInternalEx<CXX>(obj, attr, NULL, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj);
} }
if (val == NULL) { if (val == NULL) {
...@@ -4551,19 +4628,12 @@ Box* callItemOrSliceAttr(Box* target, BoxedString* item_str, BoxedString* slice_ ...@@ -4551,19 +4628,12 @@ Box* callItemOrSliceAttr(Box* target, BoxedString* item_str, BoxedString* slice_
} }
} }
// target[slice] template <enum ExceptionStyle S>
extern "C" Box* getitem(Box* target, Box* slice) { Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI) {
STAT_TIMER(t0, "us_timer_slowpath_getitem", 10); if (S == CAPI) {
assert(!rewrite_args && "implement me");
// This possibly could just be represented as a single callattr; the only tricky part rewrite_args = NULL;
// are the error messages. }
// Ex "(1)[1]" and "(1).__getitem__(1)" give different error messages.
static StatCounter slowpath_getitem("slowpath_getitem");
slowpath_getitem.log();
std::unique_ptr<Rewriter> rewriter(
Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 2, "getitem"));
// The PyObject_GetItem logic is: // The PyObject_GetItem logic is:
// - call mp_subscript if it exists // - call mp_subscript if it exists
...@@ -4575,9 +4645,10 @@ extern "C" Box* getitem(Box* target, Box* slice) { ...@@ -4575,9 +4645,10 @@ extern "C" Box* getitem(Box* target, Box* slice) {
// exist if mp_subscript exists. // exist if mp_subscript exists.
PyMappingMethods* m = target->cls->tp_as_mapping; PyMappingMethods* m = target->cls->tp_as_mapping;
if (m && m->mp_subscript && m->mp_subscript != slot_mp_subscript) { if (m && m->mp_subscript && m->mp_subscript != slot_mp_subscript) {
if (rewriter.get()) { if (rewrite_args) {
RewriterVar* r_obj = rewriter->getArg(0); assert(S == CXX);
RewriterVar* r_slice = rewriter->getArg(1); RewriterVar* r_obj = rewrite_args->target;
RewriterVar* r_slice = rewrite_args->slice;
RewriterVar* r_cls = r_obj->getAttr(offsetof(Box, cls)); RewriterVar* r_cls = r_obj->getAttr(offsetof(Box, cls));
RewriterVar* r_m = r_cls->getAttr(offsetof(BoxedClass, tp_as_mapping)); RewriterVar* r_m = r_cls->getAttr(offsetof(BoxedClass, tp_as_mapping));
r_m->addGuardNotEq(0); r_m->addGuardNotEq(0);
...@@ -4588,12 +4659,13 @@ extern "C" Box* getitem(Box* target, Box* slice) { ...@@ -4588,12 +4659,13 @@ extern "C" Box* getitem(Box* target, Box* slice) {
// (after guarding it's not null), or maybe not. But the rewriter doesn't currently // (after guarding it's not null), or maybe not. But the rewriter doesn't currently
// support calling a RewriterVar (can only call fixed function addresses). // support calling a RewriterVar (can only call fixed function addresses).
r_m->addAttrGuard(offsetof(PyMappingMethods, mp_subscript), (intptr_t)m->mp_subscript); r_m->addAttrGuard(offsetof(PyMappingMethods, mp_subscript), (intptr_t)m->mp_subscript);
RewriterVar* r_rtn = rewriter->call(true, (void*)m->mp_subscript, r_obj, r_slice); RewriterVar* r_rtn = rewrite_args->rewriter->call(true, (void*)m->mp_subscript, r_obj, r_slice);
rewriter->call(true, (void*)checkAndThrowCAPIException); rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
rewriter->commitReturning(r_rtn); rewrite_args->out_success = true;
rewrite_args->out_rtn = r_rtn;
} }
Box* r = m->mp_subscript(target, slice); Box* r = m->mp_subscript(target, slice);
if (!r) if (S == CXX && !r)
throwCAPIException(); throwCAPIException();
return r; return r;
} }
...@@ -4602,34 +4674,92 @@ extern "C" Box* getitem(Box* target, Box* slice) { ...@@ -4602,34 +4674,92 @@ extern "C" Box* getitem(Box* target, Box* slice) {
static BoxedString* getslice_str = internStringImmortal("__getslice__"); static BoxedString* getslice_str = internStringImmortal("__getslice__");
Box* rtn; Box* rtn;
if (rewriter.get()) { if (S == CAPI) {
CallRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getReturnDestination()); assert(!rewrite_args);
rewrite_args.arg1 = rewriter->getArg(1); try {
rtn = callItemOrSliceAttr(target, getitem_str, getslice_str, slice, NULL, NULL);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} else {
if (rewrite_args) {
CallRewriteArgs crewrite_args(rewrite_args->rewriter, rewrite_args->target, rewrite_args->destination);
crewrite_args.arg1 = rewrite_args->slice;
rtn = callItemOrSliceAttr(target, getitem_str, getslice_str, slice, NULL, &rewrite_args); rtn = callItemOrSliceAttr(target, getitem_str, getslice_str, slice, NULL, &crewrite_args);
if (!rewrite_args.out_success) { if (!crewrite_args.out_success) {
rewriter.reset(NULL); rewrite_args = NULL;
} else if (rtn) { } else if (rtn) {
rewriter->commitReturning(rewrite_args.out_rtn); rewrite_args->out_rtn = crewrite_args.out_rtn;
}
} else {
rtn = callItemOrSliceAttr(target, getitem_str, getslice_str, slice, NULL, NULL);
} }
} else {
rtn = callItemOrSliceAttr(target, getitem_str, getslice_str, slice, NULL, NULL);
} }
if (rtn == NULL) { if (rtn == NULL) {
// different versions of python give different error messages for this: // different versions of python give different error messages for this:
if (PYTHON_VERSION_MAJOR == 2 && PYTHON_VERSION_MINOR < 7) { if (PYTHON_VERSION_MAJOR == 2 && PYTHON_VERSION_MINOR < 7) {
raiseExcHelper(TypeError, "'%s' object is unsubscriptable", getTypeName(target)); // tested on 2.6.6 if (S == CAPI)
PyErr_Format(TypeError, "'%s' object is unsubscriptable", getTypeName(target)); // tested on 2.6.6
else
raiseExcHelper(TypeError, "'%s' object is unsubscriptable", getTypeName(target)); // tested on 2.6.6
} else if (PYTHON_VERSION_MAJOR == 2 && PYTHON_VERSION_MINOR == 7 && PYTHON_VERSION_MICRO < 3) { } else if (PYTHON_VERSION_MAJOR == 2 && PYTHON_VERSION_MINOR == 7 && PYTHON_VERSION_MICRO < 3) {
raiseExcHelper(TypeError, "'%s' object is not subscriptable", getTypeName(target)); // tested on 2.7.1 if (S == CAPI)
PyErr_Format(TypeError, "'%s' object is not subscriptable", getTypeName(target)); // tested on 2.7.1
else
raiseExcHelper(TypeError, "'%s' object is not subscriptable", getTypeName(target)); // tested on 2.7.1
} else { } else {
// Changed to this in 2.7.3: // Changed to this in 2.7.3:
raiseExcHelper(TypeError, "'%s' object has no attribute '__getitem__'", if (S == CAPI)
getTypeName(target)); // tested on 2.7.3 PyErr_Format(TypeError, "'%s' object has no attribute '__getitem__'", getTypeName(target));
else
raiseExcHelper(TypeError, "'%s' object has no attribute '__getitem__'", getTypeName(target));
} }
} }
if (rewrite_args)
rewrite_args->out_success = true;
return rtn;
}
// Force instantiation of the template
template Box* getitemInternal<CAPI>(Box*, Box*, GetitemRewriteArgs*);
template Box* getitemInternal<CXX>(Box*, Box*, GetitemRewriteArgs*);
// target[slice]
extern "C" Box* getitem(Box* target, Box* slice) {
STAT_TIMER(t0, "us_timer_slowpath_getitem", 10);
// This possibly could just be represented as a single callattr; the only tricky part
// are the error messages.
// Ex "(1)[1]" and "(1).__getitem__(1)" give different error messages.
static StatCounter slowpath_getitem("slowpath_getitem");
slowpath_getitem.log();
std::unique_ptr<Rewriter> rewriter(
Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 2, "getitem"));
Box* rtn;
if (rewriter.get()) {
GetitemRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getArg(1),
rewriter->getReturnDestination());
rtn = getitemInternal<CXX>(target, slice, &rewrite_args);
if (!rewrite_args.out_success) {
rewriter.reset(NULL);
} else {
rewriter->commitReturning(rewrite_args.out_rtn);
}
} else {
rtn = getitemInternal<CXX>(target, slice, NULL);
}
assert(rtn);
return rtn; return rtn;
} }
...@@ -5370,7 +5500,7 @@ void setGlobal(Box* globals, BoxedString* name, Box* value) { ...@@ -5370,7 +5500,7 @@ void setGlobal(Box* globals, BoxedString* name, Box* value) {
extern "C" Box* importFrom(Box* _m, BoxedString* name) { extern "C" Box* importFrom(Box* _m, BoxedString* name) {
STAT_TIMER(t0, "us_timer_importFrom", 10); STAT_TIMER(t0, "us_timer_importFrom", 10);
Box* r = getattrInternal(_m, name, NULL); Box* r = getattrInternal<CXX>(_m, name, NULL);
if (r) if (r)
return r; return r;
......
...@@ -114,6 +114,13 @@ struct CallRewriteArgs; ...@@ -114,6 +114,13 @@ struct CallRewriteArgs;
Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names); Box** args, const std::vector<BoxedString*>* keyword_names);
struct GetitemRewriteArgs;
template <ExceptionStyle::ExceptionStyle S>
Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI);
struct LenRewriteArgs;
template <ExceptionStyle::ExceptionStyle S>
BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI);
Box* lenCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* lenCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names); Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names);
...@@ -134,7 +141,8 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit ...@@ -134,7 +141,8 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
// This is the equivalent of PyObject_GetAttr. Unlike getattrInternalGeneric, it checks for custom __getattr__ or // This is the equivalent of PyObject_GetAttr. Unlike getattrInternalGeneric, it checks for custom __getattr__ or
// __getattribute__ methods. // __getattribute__ methods.
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args); template <ExceptionStyle::ExceptionStyle S>
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == ExceptionStyle::CAPI);
// This is the equivalent of PyObject_GenericGetAttr, which performs the default lookup rules for getattr() (check for // This is the equivalent of PyObject_GenericGetAttr, which performs the default lookup rules for getattr() (check for
// data descriptor, check for instance attribute, check for non-data descriptor). It does not check for __getattr__ or // data descriptor, check for instance attribute, check for non-data descriptor). It does not check for __getattr__ or
......
...@@ -97,6 +97,24 @@ struct CallRewriteArgs { ...@@ -97,6 +97,24 @@ struct CallRewriteArgs {
out_rtn(NULL) {} out_rtn(NULL) {}
}; };
struct GetitemRewriteArgs {
Rewriter* rewriter;
RewriterVar* target;
RewriterVar* slice;
Location destination;
bool out_success;
RewriterVar* out_rtn;
GetitemRewriteArgs(Rewriter* rewriter, RewriterVar* target, RewriterVar* slice, Location destination)
: rewriter(rewriter),
target(target),
slice(slice),
destination(destination),
out_success(false),
out_rtn(NULL) {}
};
struct BinopRewriteArgs { struct BinopRewriteArgs {
Rewriter* rewriter; Rewriter* rewriter;
RewriterVar* lhs; RewriterVar* lhs;
......
...@@ -1654,7 +1654,7 @@ static Box* instancemethodRepr(Box* b) { ...@@ -1654,7 +1654,7 @@ static Box* instancemethodRepr(Box* b) {
const char* sfuncname = "?", * sklassname = "?"; const char* sfuncname = "?", * sklassname = "?";
static BoxedString* name_str = internStringImmortal("__name__"); static BoxedString* name_str = internStringImmortal("__name__");
funcname = getattrInternal(func, name_str, NULL); funcname = getattrInternal<ExceptionStyle::CXX>(func, name_str, NULL);
if (funcname != NULL) { if (funcname != NULL) {
if (!PyString_Check(funcname)) { if (!PyString_Check(funcname)) {
...@@ -1666,7 +1666,7 @@ static Box* instancemethodRepr(Box* b) { ...@@ -1666,7 +1666,7 @@ static Box* instancemethodRepr(Box* b) {
if (klass == NULL) { if (klass == NULL) {
klassname = NULL; klassname = NULL;
} else { } else {
klassname = getattrInternal(klass, name_str, NULL); klassname = getattrInternal<ExceptionStyle::CXX>(klass, name_str, NULL);
if (klassname != NULL) { if (klassname != NULL) {
if (!PyString_Check(klassname)) { if (!PyString_Check(klassname)) {
klassname = NULL; klassname = 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