mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
Optimizations by Sjoerd:
- define tp_getattro, tp_setattro - use precreated string objects for most common exceptions and method names
This commit is contained in:
parent
d8eb1b340f
commit
2878a69922
1 changed files with 172 additions and 81 deletions
|
@ -28,8 +28,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
/* Forward */
|
/* Forward */
|
||||||
static object *class_lookup PROTO((classobject *, char *, classobject **));
|
static object *class_lookup PROTO((classobject *, object *, classobject **));
|
||||||
static object *instance_getattr1 PROTO((instanceobject *, char *));
|
static object *instance_getattr1 PROTO((instanceobject *, object *));
|
||||||
|
|
||||||
object *
|
object *
|
||||||
newclassobject(bases, dict, name)
|
newclassobject(bases, dict, name)
|
||||||
|
@ -40,6 +40,7 @@ newclassobject(bases, dict, name)
|
||||||
int pos;
|
int pos;
|
||||||
object *key, *value;
|
object *key, *value;
|
||||||
classobject *op, *dummy;
|
classobject *op, *dummy;
|
||||||
|
static object *getattrstr, *setattrstr, *delattrstr;
|
||||||
if (dictlookup(dict, "__doc__") == NULL) {
|
if (dictlookup(dict, "__doc__") == NULL) {
|
||||||
if (dictinsert(dict, "__doc__", None) < 0)
|
if (dictinsert(dict, "__doc__", None) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -61,9 +62,14 @@ newclassobject(bases, dict, name)
|
||||||
op->cl_dict = dict;
|
op->cl_dict = dict;
|
||||||
XINCREF(name);
|
XINCREF(name);
|
||||||
op->cl_name = name;
|
op->cl_name = name;
|
||||||
op->cl_getattr = class_lookup(op, "__getattr__", &dummy);
|
if (getattrstr == NULL) {
|
||||||
op->cl_setattr = class_lookup(op, "__setattr__", &dummy);
|
getattrstr = newstringobject("__getattr__");
|
||||||
op->cl_delattr = class_lookup(op, "__delattr__", &dummy);
|
setattrstr = newstringobject("__setattr__");
|
||||||
|
delattrstr = newstringobject("__delattr__");
|
||||||
|
}
|
||||||
|
op->cl_getattr = class_lookup(op, getattrstr, &dummy);
|
||||||
|
op->cl_setattr = class_lookup(op, setattrstr, &dummy);
|
||||||
|
op->cl_delattr = class_lookup(op, delattrstr, &dummy);
|
||||||
XINCREF(op->cl_getattr);
|
XINCREF(op->cl_getattr);
|
||||||
XINCREF(op->cl_setattr);
|
XINCREF(op->cl_setattr);
|
||||||
XINCREF(op->cl_delattr);
|
XINCREF(op->cl_delattr);
|
||||||
|
@ -90,11 +96,11 @@ class_dealloc(op)
|
||||||
static object *
|
static object *
|
||||||
class_lookup(cp, name, pclass)
|
class_lookup(cp, name, pclass)
|
||||||
classobject *cp;
|
classobject *cp;
|
||||||
char *name;
|
object *name;
|
||||||
classobject **pclass;
|
classobject **pclass;
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
object *value = dictlookup(cp->cl_dict, name);
|
object *value = mappinglookup(cp->cl_dict, name);
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
*pclass = cp;
|
*pclass = cp;
|
||||||
return value;
|
return value;
|
||||||
|
@ -112,12 +118,13 @@ class_lookup(cp, name, pclass)
|
||||||
static object *
|
static object *
|
||||||
class_getattr(op, name)
|
class_getattr(op, name)
|
||||||
register classobject *op;
|
register classobject *op;
|
||||||
register char *name;
|
object *name;
|
||||||
{
|
{
|
||||||
register object *v;
|
register object *v;
|
||||||
|
register char *sname = getstringvalue(name);
|
||||||
classobject *class;
|
classobject *class;
|
||||||
if (name[0] == '_' && name[1] == '_') {
|
if (sname[0] == '_' && sname[1] == '_') {
|
||||||
if (strcmp(name, "__dict__") == 0) {
|
if (strcmp(sname, "__dict__") == 0) {
|
||||||
if (getrestricted()) {
|
if (getrestricted()) {
|
||||||
err_setstr(RuntimeError,
|
err_setstr(RuntimeError,
|
||||||
"class.__dict__ not accessible in restricted mode");
|
"class.__dict__ not accessible in restricted mode");
|
||||||
|
@ -126,11 +133,11 @@ class_getattr(op, name)
|
||||||
INCREF(op->cl_dict);
|
INCREF(op->cl_dict);
|
||||||
return op->cl_dict;
|
return op->cl_dict;
|
||||||
}
|
}
|
||||||
if (strcmp(name, "__bases__") == 0) {
|
if (strcmp(sname, "__bases__") == 0) {
|
||||||
INCREF(op->cl_bases);
|
INCREF(op->cl_bases);
|
||||||
return op->cl_bases;
|
return op->cl_bases;
|
||||||
}
|
}
|
||||||
if (strcmp(name, "__name__") == 0) {
|
if (strcmp(sname, "__name__") == 0) {
|
||||||
if (op->cl_name == NULL)
|
if (op->cl_name == NULL)
|
||||||
v = None;
|
v = None;
|
||||||
else
|
else
|
||||||
|
@ -141,7 +148,7 @@ class_getattr(op, name)
|
||||||
}
|
}
|
||||||
v = class_lookup(op, name, &class);
|
v = class_lookup(op, name, &class);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
err_setstr(AttributeError, name);
|
err_setval(AttributeError, name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (is_accessobject(v)) {
|
if (is_accessobject(v)) {
|
||||||
|
@ -163,13 +170,14 @@ class_getattr(op, name)
|
||||||
static int
|
static int
|
||||||
class_setattr(op, name, v)
|
class_setattr(op, name, v)
|
||||||
classobject *op;
|
classobject *op;
|
||||||
char *name;
|
object *name;
|
||||||
object *v;
|
object *v;
|
||||||
{
|
{
|
||||||
object *ac;
|
object *ac;
|
||||||
if (name[0] == '_' && name[1] == '_') {
|
char *sname = getstringvalue(name);
|
||||||
int n = strlen(name);
|
if (sname[0] == '_' && sname[1] == '_') {
|
||||||
if (name[n-1] == '_' && name[n-2] == '_') {
|
int n = getstringsize(name);
|
||||||
|
if (sname[n-1] == '_' && sname[n-2] == '_') {
|
||||||
err_setstr(TypeError, "read-only special attribute");
|
err_setstr(TypeError, "read-only special attribute");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -179,18 +187,18 @@ class_setattr(op, name, v)
|
||||||
"classes are read-only in restricted mode");
|
"classes are read-only in restricted mode");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ac = dictlookup(op->cl_dict, name);
|
ac = mappinglookup(op->cl_dict, name);
|
||||||
if (ac != NULL && is_accessobject(ac))
|
if (ac != NULL && is_accessobject(ac))
|
||||||
return setaccessvalue(ac, getowner(), v);
|
return setaccessvalue(ac, getowner(), v);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
int rv = dictremove(op->cl_dict, name);
|
int rv = mappingremove(op->cl_dict, name);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
err_setstr(AttributeError,
|
err_setstr(AttributeError,
|
||||||
"delete non-existing class attribute");
|
"delete non-existing class attribute");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return dictinsert(op->cl_dict, name, v);
|
return mappinginsert(op->cl_dict, name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static object *
|
static object *
|
||||||
|
@ -215,13 +223,18 @@ typeobject Classtype = {
|
||||||
0,
|
0,
|
||||||
(destructor)class_dealloc, /*tp_dealloc*/
|
(destructor)class_dealloc, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
(getattrfunc)class_getattr, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
(setattrfunc)class_setattr, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
(reprfunc)class_repr, /*tp_repr*/
|
(reprfunc)class_repr, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
|
0, /*tp_hash*/
|
||||||
|
0, /*tp_call*/
|
||||||
|
0, /*tp_str*/
|
||||||
|
(getattrofunc)class_getattr, /*tp_getattro*/
|
||||||
|
(setattrofunc)class_setattr, /*tp_setattro*/
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -291,6 +304,7 @@ newinstanceobject(class, arg, kw)
|
||||||
{
|
{
|
||||||
register instanceobject *inst;
|
register instanceobject *inst;
|
||||||
object *init;
|
object *init;
|
||||||
|
static object *initstr;
|
||||||
if (!is_classobject(class)) {
|
if (!is_classobject(class)) {
|
||||||
err_badcall();
|
err_badcall();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -306,7 +320,9 @@ newinstanceobject(class, arg, kw)
|
||||||
DECREF(inst);
|
DECREF(inst);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
init = instance_getattr1(inst, "__init__");
|
if (initstr == NULL)
|
||||||
|
initstr = newstringobject("__init__");
|
||||||
|
init = instance_getattr1(inst, initstr);
|
||||||
if (init == NULL) {
|
if (init == NULL) {
|
||||||
err_clear();
|
err_clear();
|
||||||
if (arg != NULL && (!is_tupleobject(arg) ||
|
if (arg != NULL && (!is_tupleobject(arg) ||
|
||||||
|
@ -345,6 +361,7 @@ instance_dealloc(inst)
|
||||||
{
|
{
|
||||||
object *error_type, *error_value, *error_traceback;
|
object *error_type, *error_value, *error_traceback;
|
||||||
object *del;
|
object *del;
|
||||||
|
static object *delstr;
|
||||||
/* Call the __del__ method if it exists. First temporarily
|
/* Call the __del__ method if it exists. First temporarily
|
||||||
revive the object and save the current exception, if any. */
|
revive the object and save the current exception, if any. */
|
||||||
#ifdef Py_TRACE_REFS
|
#ifdef Py_TRACE_REFS
|
||||||
|
@ -360,7 +377,9 @@ instance_dealloc(inst)
|
||||||
INCREF(inst);
|
INCREF(inst);
|
||||||
#endif /* !Py_TRACE_REFS */
|
#endif /* !Py_TRACE_REFS */
|
||||||
err_fetch(&error_type, &error_value, &error_traceback);
|
err_fetch(&error_type, &error_value, &error_traceback);
|
||||||
if ((del = instance_getattr1(inst, "__del__")) != NULL) {
|
if (delstr == NULL)
|
||||||
|
delstr = newstringobject("__del__");
|
||||||
|
if ((del = instance_getattr1(inst, delstr)) != NULL) {
|
||||||
object *res = call_object(del, (object *)NULL);
|
object *res = call_object(del, (object *)NULL);
|
||||||
DECREF(del);
|
DECREF(del);
|
||||||
XDECREF(res);
|
XDECREF(res);
|
||||||
|
@ -390,12 +409,13 @@ instance_dealloc(inst)
|
||||||
static object *
|
static object *
|
||||||
instance_getattr1(inst, name)
|
instance_getattr1(inst, name)
|
||||||
register instanceobject *inst;
|
register instanceobject *inst;
|
||||||
register char *name;
|
object *name;
|
||||||
{
|
{
|
||||||
register object *v;
|
register object *v;
|
||||||
|
register char *sname = getstringvalue(name);
|
||||||
classobject *class;
|
classobject *class;
|
||||||
if (name[0] == '_' && name[1] == '_') {
|
if (sname[0] == '_' && sname[1] == '_') {
|
||||||
if (strcmp(name, "__dict__") == 0) {
|
if (strcmp(sname, "__dict__") == 0) {
|
||||||
if (getrestricted()) {
|
if (getrestricted()) {
|
||||||
err_setstr(RuntimeError,
|
err_setstr(RuntimeError,
|
||||||
"instance.__dict__ not accessible in restricted mode");
|
"instance.__dict__ not accessible in restricted mode");
|
||||||
|
@ -404,17 +424,17 @@ instance_getattr1(inst, name)
|
||||||
INCREF(inst->in_dict);
|
INCREF(inst->in_dict);
|
||||||
return inst->in_dict;
|
return inst->in_dict;
|
||||||
}
|
}
|
||||||
if (strcmp(name, "__class__") == 0) {
|
if (strcmp(sname, "__class__") == 0) {
|
||||||
INCREF(inst->in_class);
|
INCREF(inst->in_class);
|
||||||
return (object *)inst->in_class;
|
return (object *)inst->in_class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class = NULL;
|
class = NULL;
|
||||||
v = dictlookup(inst->in_dict, name);
|
v = mappinglookup(inst->in_dict, name);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
v = class_lookup(inst->in_class, name, &class);
|
v = class_lookup(inst->in_class, name, &class);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
err_setstr(AttributeError, name);
|
err_setval(AttributeError, name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,14 +470,14 @@ instance_getattr1(inst, name)
|
||||||
static object *
|
static object *
|
||||||
instance_getattr(inst, name)
|
instance_getattr(inst, name)
|
||||||
register instanceobject *inst;
|
register instanceobject *inst;
|
||||||
register char *name;
|
object *name;
|
||||||
{
|
{
|
||||||
register object *func, *res;
|
register object *func, *res;
|
||||||
res = instance_getattr1(inst, name);
|
res = instance_getattr1(inst, name);
|
||||||
if (res == NULL && (func = inst->in_class->cl_getattr) != NULL) {
|
if (res == NULL && (func = inst->in_class->cl_getattr) != NULL) {
|
||||||
object *args;
|
object *args;
|
||||||
err_clear();
|
err_clear();
|
||||||
args = mkvalue("(Os)", inst, name);
|
args = mkvalue("(OO)", inst, name);
|
||||||
if (args == NULL)
|
if (args == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
res = call_object(func, args);
|
res = call_object(func, args);
|
||||||
|
@ -469,36 +489,37 @@ instance_getattr(inst, name)
|
||||||
static int
|
static int
|
||||||
instance_setattr1(inst, name, v)
|
instance_setattr1(inst, name, v)
|
||||||
instanceobject *inst;
|
instanceobject *inst;
|
||||||
char *name;
|
object *name;
|
||||||
object *v;
|
object *v;
|
||||||
{
|
{
|
||||||
object *ac;
|
object *ac;
|
||||||
ac = dictlookup(inst->in_dict, name);
|
ac = mappinglookup(inst->in_dict, name);
|
||||||
if (ac != NULL && is_accessobject(ac))
|
if (ac != NULL && is_accessobject(ac))
|
||||||
return setaccessvalue(ac, getowner(), v);
|
return setaccessvalue(ac, getowner(), v);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
int rv = dictremove(inst->in_dict, name);
|
int rv = mappingremove(inst->in_dict, name);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
err_setstr(AttributeError,
|
err_setstr(AttributeError,
|
||||||
"delete non-existing instance attribute");
|
"delete non-existing instance attribute");
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return dictinsert(inst->in_dict, name, v);
|
return mappinginsert(inst->in_dict, name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
instance_setattr(inst, name, v)
|
instance_setattr(inst, name, v)
|
||||||
instanceobject *inst;
|
instanceobject *inst;
|
||||||
char *name;
|
object *name;
|
||||||
object *v;
|
object *v;
|
||||||
{
|
{
|
||||||
object *func, *args, *res;
|
object *func, *args, *res;
|
||||||
if (name[0] == '_' && name[1] == '_'
|
char *sname = getstringvalue(name);
|
||||||
&& (strcmp(name, "__dict__") == 0 ||
|
if (sname[0] == '_' && sname[1] == '_'
|
||||||
strcmp(name, "__class__") == 0)) {
|
&& (strcmp(sname, "__dict__") == 0 ||
|
||||||
int n = strlen(name);
|
strcmp(sname, "__class__") == 0)) {
|
||||||
if (name[n-1] == '_' && name[n-2] == '_') {
|
int n = strlen(sname);
|
||||||
|
if (sname[n-1] == '_' && sname[n-2] == '_') {
|
||||||
err_setstr(TypeError, "read-only special attribute");
|
err_setstr(TypeError, "read-only special attribute");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -510,9 +531,9 @@ instance_setattr(inst, name, v)
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return instance_setattr1(inst, name, v);
|
return instance_setattr1(inst, name, v);
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
args = mkvalue("(Os)", inst, name);
|
args = mkvalue("(OO)", inst, name);
|
||||||
else
|
else
|
||||||
args = mkvalue("(OsO)", inst, name, v);
|
args = mkvalue("(OOO)", inst, name, v);
|
||||||
if (args == NULL)
|
if (args == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
res = call_object(func, args);
|
res = call_object(func, args);
|
||||||
|
@ -529,8 +550,11 @@ instance_repr(inst)
|
||||||
{
|
{
|
||||||
object *func;
|
object *func;
|
||||||
object *res;
|
object *res;
|
||||||
|
static object *reprstr;
|
||||||
|
|
||||||
func = instance_getattr(inst, "__repr__");
|
if (reprstr == NULL)
|
||||||
|
reprstr = newstringobject("__repr__");
|
||||||
|
func = instance_getattr(inst, reprstr);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
char buf[140];
|
char buf[140];
|
||||||
object *classname = inst->in_class->cl_name;
|
object *classname = inst->in_class->cl_name;
|
||||||
|
@ -584,13 +608,18 @@ instance_hash(inst)
|
||||||
object *func;
|
object *func;
|
||||||
object *res;
|
object *res;
|
||||||
long outcome;
|
long outcome;
|
||||||
|
static object *hashstr, *cmpstr;
|
||||||
|
|
||||||
func = instance_getattr(inst, "__hash__");
|
if (hashstr == NULL)
|
||||||
|
hashstr = newstringobject("__hash__");
|
||||||
|
func = instance_getattr(inst, hashstr);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
/* If there is no __cmp__ method, we hash on the address.
|
/* If there is no __cmp__ method, we hash on the address.
|
||||||
If a __cmp__ method exists, there must be a __hash__. */
|
If a __cmp__ method exists, there must be a __hash__. */
|
||||||
err_clear();
|
err_clear();
|
||||||
func = instance_getattr(inst, "__cmp__");
|
if (cmpstr == NULL)
|
||||||
|
cmpstr = newstringobject("__cmp__");
|
||||||
|
func = instance_getattr(inst, cmpstr);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
err_clear();
|
err_clear();
|
||||||
outcome = (long)inst;
|
outcome = (long)inst;
|
||||||
|
@ -618,6 +647,8 @@ instance_hash(inst)
|
||||||
return outcome;
|
return outcome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static object *getitemstr, *setitemstr, *delitemstr, *lenstr;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
instance_length(inst)
|
instance_length(inst)
|
||||||
instanceobject *inst;
|
instanceobject *inst;
|
||||||
|
@ -626,7 +657,9 @@ instance_length(inst)
|
||||||
object *res;
|
object *res;
|
||||||
int outcome;
|
int outcome;
|
||||||
|
|
||||||
func = instance_getattr(inst, "__len__");
|
if (lenstr == NULL)
|
||||||
|
lenstr = newstringobject("__len__");
|
||||||
|
func = instance_getattr(inst, lenstr);
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
res = call_object(func, (object *)NULL);
|
res = call_object(func, (object *)NULL);
|
||||||
|
@ -655,7 +688,9 @@ instance_subscript(inst, key)
|
||||||
object *arg;
|
object *arg;
|
||||||
object *res;
|
object *res;
|
||||||
|
|
||||||
func = instance_getattr(inst, "__getitem__");
|
if (getitemstr == NULL)
|
||||||
|
getitemstr = newstringobject("__getitem__");
|
||||||
|
func = instance_getattr(inst, getitemstr);
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
arg = mkvalue("(O)", key);
|
arg = mkvalue("(O)", key);
|
||||||
|
@ -679,10 +714,16 @@ instance_ass_subscript(inst, key, value)
|
||||||
object *arg;
|
object *arg;
|
||||||
object *res;
|
object *res;
|
||||||
|
|
||||||
if (value == NULL)
|
if (value == NULL) {
|
||||||
func = instance_getattr(inst, "__delitem__");
|
if (delitemstr == NULL)
|
||||||
else
|
delitemstr = newstringobject("__delitem__");
|
||||||
func = instance_getattr(inst, "__setitem__");
|
func = instance_getattr(inst, delitemstr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (setitemstr == NULL)
|
||||||
|
setitemstr = newstringobject("__setitem__");
|
||||||
|
func = instance_getattr(inst, setitemstr);
|
||||||
|
}
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
|
@ -715,7 +756,9 @@ instance_item(inst, i)
|
||||||
{
|
{
|
||||||
object *func, *arg, *res;
|
object *func, *arg, *res;
|
||||||
|
|
||||||
func = instance_getattr(inst, "__getitem__");
|
if (getitemstr == NULL)
|
||||||
|
getitemstr = newstringobject("__getitem__");
|
||||||
|
func = instance_getattr(inst, getitemstr);
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
arg = mkvalue("(i)", i);
|
arg = mkvalue("(i)", i);
|
||||||
|
@ -735,8 +778,11 @@ instance_slice(inst, i, j)
|
||||||
int i, j;
|
int i, j;
|
||||||
{
|
{
|
||||||
object *func, *arg, *res;
|
object *func, *arg, *res;
|
||||||
|
static object *getslicestr;
|
||||||
|
|
||||||
func = instance_getattr(inst, "__getslice__");
|
if (getslicestr == NULL)
|
||||||
|
getslicestr = newstringobject("__getslice__");
|
||||||
|
func = instance_getattr(inst, getslicestr);
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
arg = mkvalue("(ii)", i, j);
|
arg = mkvalue("(ii)", i, j);
|
||||||
|
@ -758,10 +804,16 @@ instance_ass_item(inst, i, item)
|
||||||
{
|
{
|
||||||
object *func, *arg, *res;
|
object *func, *arg, *res;
|
||||||
|
|
||||||
if (item == NULL)
|
if (item == NULL) {
|
||||||
func = instance_getattr(inst, "__delitem__");
|
if (delitemstr == NULL)
|
||||||
else
|
delitemstr = newstringobject("__delitem__");
|
||||||
func = instance_getattr(inst, "__setitem__");
|
func = instance_getattr(inst, delitemstr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (setitemstr == NULL)
|
||||||
|
setitemstr = newstringobject("__setitem__");
|
||||||
|
func = instance_getattr(inst, setitemstr);
|
||||||
|
}
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
|
@ -788,11 +840,18 @@ instance_ass_slice(inst, i, j, value)
|
||||||
object *value;
|
object *value;
|
||||||
{
|
{
|
||||||
object *func, *arg, *res;
|
object *func, *arg, *res;
|
||||||
|
static object *setslicestr, *delslicestr;
|
||||||
|
|
||||||
if (value == NULL)
|
if (value == NULL) {
|
||||||
func = instance_getattr(inst, "__delslice__");
|
if (delslicestr == NULL)
|
||||||
else
|
delslicestr = newstringobject("__delslice__");
|
||||||
func = instance_getattr(inst, "__setslice__");
|
func = instance_getattr(inst, delslicestr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (setslicestr == NULL)
|
||||||
|
setslicestr = newstringobject("__setslice__");
|
||||||
|
func = instance_getattr(inst, setslicestr);
|
||||||
|
}
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
|
@ -825,7 +884,7 @@ static sequence_methods instance_as_sequence = {
|
||||||
static object *
|
static object *
|
||||||
generic_unary_op(self, methodname)
|
generic_unary_op(self, methodname)
|
||||||
instanceobject *self;
|
instanceobject *self;
|
||||||
char *methodname;
|
object *methodname;
|
||||||
{
|
{
|
||||||
object *func, *res;
|
object *func, *res;
|
||||||
|
|
||||||
|
@ -838,8 +897,8 @@ generic_unary_op(self, methodname)
|
||||||
|
|
||||||
|
|
||||||
/* Forward */
|
/* Forward */
|
||||||
static int halfbinop PROTO((object *, object *, char *, object **,
|
static int halfbinop Py_PROTO((object *, object *, char *, object **,
|
||||||
object * (*) PROTO((object *, object *)), int ));
|
object * (*) Py_PROTO((object *, object *)), int ));
|
||||||
|
|
||||||
|
|
||||||
/* Implement a binary operator involving at least one class instance. */
|
/* Implement a binary operator involving at least one class instance. */
|
||||||
|
@ -871,6 +930,8 @@ instancebinop(v, w, opname, ropname, thisfunc)
|
||||||
1 if we could try another operation
|
1 if we could try another operation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static object *coerce_obj;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
halfbinop(v, w, opname, r_result, thisfunc, swapped)
|
halfbinop(v, w, opname, r_result, thisfunc, swapped)
|
||||||
object *v;
|
object *v;
|
||||||
|
@ -888,7 +949,12 @@ halfbinop(v, w, opname, r_result, thisfunc, swapped)
|
||||||
|
|
||||||
if (!is_instanceobject(v))
|
if (!is_instanceobject(v))
|
||||||
return 1;
|
return 1;
|
||||||
coerce = getattr(v, "__coerce__");
|
if (coerce_obj == NULL) {
|
||||||
|
coerce_obj = newstringobject("__coerce__");
|
||||||
|
if (coerce_obj == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
coerce = getattro(v, coerce_obj);
|
||||||
if (coerce == NULL) {
|
if (coerce == NULL) {
|
||||||
err_clear();
|
err_clear();
|
||||||
}
|
}
|
||||||
|
@ -960,7 +1026,12 @@ instance_coerce(pv, pw)
|
||||||
object *args;
|
object *args;
|
||||||
object *coerced;
|
object *coerced;
|
||||||
|
|
||||||
coerce = getattr(v, "__coerce__");
|
if (coerce_obj == NULL) {
|
||||||
|
coerce_obj = newstringobject("__coerce__");
|
||||||
|
if (coerce_obj == NULL)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
coerce = getattro(v, coerce_obj);
|
||||||
if (coerce == NULL) {
|
if (coerce == NULL) {
|
||||||
/* No __coerce__ method: always OK */
|
/* No __coerce__ method: always OK */
|
||||||
err_clear();
|
err_clear();
|
||||||
|
@ -1004,7 +1075,9 @@ instance_coerce(pv, pw)
|
||||||
|
|
||||||
#define UNARY(funcname, methodname) \
|
#define UNARY(funcname, methodname) \
|
||||||
static object *funcname(self) instanceobject *self; { \
|
static object *funcname(self) instanceobject *self; { \
|
||||||
return generic_unary_op(self, methodname); \
|
static object *o; \
|
||||||
|
if (o == NULL) o = newstringobject(methodname); \
|
||||||
|
return generic_unary_op(self, o); \
|
||||||
}
|
}
|
||||||
|
|
||||||
UNARY(instance_neg, "__neg__")
|
UNARY(instance_neg, "__neg__")
|
||||||
|
@ -1017,10 +1090,15 @@ instance_nonzero(self)
|
||||||
{
|
{
|
||||||
object *func, *res;
|
object *func, *res;
|
||||||
long outcome;
|
long outcome;
|
||||||
|
static object *nonzerostr;
|
||||||
|
|
||||||
if ((func = instance_getattr(self, "__nonzero__")) == NULL) {
|
if (nonzerostr == NULL)
|
||||||
|
nonzerostr = newstringobject("__nonzero__");
|
||||||
|
if ((func = instance_getattr(self, nonzerostr)) == NULL) {
|
||||||
err_clear();
|
err_clear();
|
||||||
if ((func = instance_getattr(self, "__len__")) == NULL) {
|
if (lenstr == NULL)
|
||||||
|
lenstr = newstringobject("__len__");
|
||||||
|
if ((func = instance_getattr(self, lenstr)) == NULL) {
|
||||||
err_clear();
|
err_clear();
|
||||||
/* Fall back to the default behavior:
|
/* Fall back to the default behavior:
|
||||||
all instances are nonzero */
|
all instances are nonzero */
|
||||||
|
@ -1063,7 +1141,11 @@ instance_pow(v, w, z)
|
||||||
object *func;
|
object *func;
|
||||||
object *args;
|
object *args;
|
||||||
object *result;
|
object *result;
|
||||||
func = getattr(v, "__pow__");
|
static object *powstr;
|
||||||
|
|
||||||
|
if (powstr == NULL)
|
||||||
|
powstr = newstringobject("__pow__");
|
||||||
|
func = getattro(v, powstr);
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
args = mkvalue("(OO)", w, z);
|
args = mkvalue("(OO)", w, z);
|
||||||
|
@ -1111,14 +1193,18 @@ typeobject Instancetype = {
|
||||||
0,
|
0,
|
||||||
(destructor)instance_dealloc, /*tp_dealloc*/
|
(destructor)instance_dealloc, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
(getattrfunc)instance_getattr, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
(setattrfunc)instance_setattr, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
instance_compare, /*tp_compare*/
|
instance_compare, /*tp_compare*/
|
||||||
(reprfunc)instance_repr, /*tp_repr*/
|
(reprfunc)instance_repr, /*tp_repr*/
|
||||||
&instance_as_number, /*tp_as_number*/
|
&instance_as_number, /*tp_as_number*/
|
||||||
&instance_as_sequence, /*tp_as_sequence*/
|
&instance_as_sequence, /*tp_as_sequence*/
|
||||||
&instance_as_mapping, /*tp_as_mapping*/
|
&instance_as_mapping, /*tp_as_mapping*/
|
||||||
(hashfunc)instance_hash, /*tp_hash*/
|
(hashfunc)instance_hash, /*tp_hash*/
|
||||||
|
0, /*tp_call*/
|
||||||
|
0, /*tp_str*/
|
||||||
|
(getattrofunc)instance_getattr, /*tp_getattro*/
|
||||||
|
(setattrofunc)instance_setattr, /*tp_setattro*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1208,15 +1294,16 @@ static struct memberlist instancemethod_memberlist[] = {
|
||||||
static object *
|
static object *
|
||||||
instancemethod_getattr(im, name)
|
instancemethod_getattr(im, name)
|
||||||
register instancemethodobject *im;
|
register instancemethodobject *im;
|
||||||
char *name;
|
object *name;
|
||||||
{
|
{
|
||||||
if (name[0] == '_') {
|
char *sname = getstringvalue(name);
|
||||||
|
if (sname[0] == '_') {
|
||||||
funcobject *func = (funcobject *)(im->im_func);
|
funcobject *func = (funcobject *)(im->im_func);
|
||||||
if (strcmp(name, "__name__") == 0) {
|
if (strcmp(sname, "__name__") == 0) {
|
||||||
INCREF(func->func_name);
|
INCREF(func->func_name);
|
||||||
return func->func_name;
|
return func->func_name;
|
||||||
}
|
}
|
||||||
if (strcmp(name, "__doc__") == 0) {
|
if (strcmp(sname, "__doc__") == 0) {
|
||||||
INCREF(func->func_doc);
|
INCREF(func->func_doc);
|
||||||
return func->func_doc;
|
return func->func_doc;
|
||||||
}
|
}
|
||||||
|
@ -1226,7 +1313,7 @@ instancemethod_getattr(im, name)
|
||||||
"instance-method attributes not accessible in restricted mode");
|
"instance-method attributes not accessible in restricted mode");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return getmember((char *)im, instancemethod_memberlist, name);
|
return getmember((char *)im, instancemethod_memberlist, sname);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1307,7 +1394,7 @@ typeobject Instancemethodtype = {
|
||||||
0,
|
0,
|
||||||
(destructor)instancemethod_dealloc, /*tp_dealloc*/
|
(destructor)instancemethod_dealloc, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
(getattrfunc)instancemethod_getattr, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
0, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
(cmpfunc)instancemethod_compare, /*tp_compare*/
|
(cmpfunc)instancemethod_compare, /*tp_compare*/
|
||||||
(reprfunc)instancemethod_repr, /*tp_repr*/
|
(reprfunc)instancemethod_repr, /*tp_repr*/
|
||||||
|
@ -1315,4 +1402,8 @@ typeobject Instancemethodtype = {
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
(hashfunc)instancemethod_hash, /*tp_hash*/
|
(hashfunc)instancemethod_hash, /*tp_hash*/
|
||||||
|
0, /*tp_call*/
|
||||||
|
0, /*tp_str*/
|
||||||
|
(getattrofunc)instancemethod_getattr, /*tp_getattro*/
|
||||||
|
0, /*tp_setattro*/
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue