Commit 39e438e8 authored by Guido van Rossum's avatar Guido van Rossum

* Objects/classobject.c: added 5th (function) parameter to

	instancebinop, to support things like Rational * float; added
	documentation strings to classes and methods
parent 4c89cb1c
...@@ -40,6 +40,10 @@ newclassobject(bases, dict, name) ...@@ -40,6 +40,10 @@ newclassobject(bases, dict, name)
int pos; int pos;
object *key, *value; object *key, *value;
classobject *op, *dummy; classobject *op, *dummy;
if (dictlookup(dict, "__doc__") == NULL) {
if (dictinsert(dict, "__doc__", None) < 0)
return NULL;
}
if (bases == NULL) { if (bases == NULL) {
bases = newtupleobject(0); bases = newtupleobject(0);
if (bases == NULL) if (bases == NULL)
...@@ -515,22 +519,28 @@ instance_repr(inst) ...@@ -515,22 +519,28 @@ instance_repr(inst)
return res; return res;
} }
static object *
instance_compare1(inst, other)
object *inst, *other;
{
return instancebinop(inst, other, "__cmp__", "__rcmp__",
instance_compare1);
}
static int static int
instance_compare(inst, other) instance_compare(inst, other)
object *inst, *other; object *inst, *other;
{ {
object *result; object *result;
int outcome; long outcome;
result = instancebinop(inst, other, "__cmp__", "__rcmp__"); result = instance_compare1(inst, other);
if (result == NULL) { if (result == NULL || !is_intobject(result)) {
error: error:
err_clear(); err_clear();
return (inst < other) ? -1 : 1; return (inst < other) ? -1 : 1;
} }
outcome = getintvalue(result); outcome = getintvalue(result);
DECREF(result); DECREF(result);
if (outcome == -1 && err_occurred())
goto error;
if (outcome < 0) if (outcome < 0)
return -1; return -1;
else if (outcome > 0) else if (outcome > 0)
...@@ -799,23 +809,26 @@ generic_unary_op(self, methodname) ...@@ -799,23 +809,26 @@ generic_unary_op(self, methodname)
/* Forward */ /* Forward */
static int halfbinop PROTO((object *, object *, char *, object **)); static int halfbinop PROTO((object *, object *, char *, object **,
object * (*) PROTO((object *, object *)), int ));
/* Implement a binary operator involving at least one class instance. */ /* Implement a binary operator involving at least one class instance. */
object * object *
instancebinop(v, w, opname, ropname) instancebinop(v, w, opname, ropname, thisfunc)
object *v; object *v;
object *w; object *w;
char *opname; char *opname;
char *ropname; char *ropname;
object * (*thisfunc) PROTO((object *, object *));
{ {
object *v1, *w1;
char buf[256]; char buf[256];
object *result = NULL; object *result = NULL;
if (halfbinop(v, w, opname, &result) <= 0) if (halfbinop(v, w, opname, &result, thisfunc, 0) <= 0)
return result; return result;
if (halfbinop(w, v, ropname, &result) <= 0) if (halfbinop(w, v, ropname, &result, thisfunc, 1) <= 0)
return result; return result;
sprintf(buf, "%s nor %s defined for these operands", opname, ropname); sprintf(buf, "%s nor %s defined for these operands", opname, ropname);
err_setstr(TypeError, buf); err_setstr(TypeError, buf);
...@@ -831,11 +844,13 @@ instancebinop(v, w, opname, ropname) ...@@ -831,11 +844,13 @@ instancebinop(v, w, opname, ropname)
*/ */
static int static int
halfbinop(v, w, opname, r_result) halfbinop(v, w, opname, r_result, thisfunc, swapped)
object *v; object *v;
object *w; object *w;
char *opname; char *opname;
object **r_result; object **r_result;
object * (*thisfunc) PROTO((object *, object *));
int swapped;
{ {
object *func; object *func;
object *args; object *args;
...@@ -845,13 +860,6 @@ halfbinop(v, w, opname, r_result) ...@@ -845,13 +860,6 @@ halfbinop(v, w, opname, r_result)
if (!is_instanceobject(v)) if (!is_instanceobject(v))
return 1; return 1;
func = getattr(v, opname);
if (func == NULL) {
if (err_occurred() != AttributeError)
return -1;
err_clear();
return 1;
}
coerce = getattr(v, "__coerce__"); coerce = getattr(v, "__coerce__");
if (coerce == NULL) { if (coerce == NULL) {
err_clear(); err_clear();
...@@ -859,39 +867,47 @@ halfbinop(v, w, opname, r_result) ...@@ -859,39 +867,47 @@ halfbinop(v, w, opname, r_result)
else { else {
args = mkvalue("(O)", w); args = mkvalue("(O)", w);
if (args == NULL) { if (args == NULL) {
DECREF(func);
return -1; return -1;
} }
coerced = call_object(coerce, args); coerced = call_object(coerce, args);
DECREF(args); DECREF(args);
DECREF(coerce); DECREF(coerce);
if (coerced == NULL) { if (coerced == NULL) {
DECREF(func);
return -1; return -1;
} }
if (coerced == None) { if (coerced == None) {
DECREF(coerced); DECREF(coerced);
DECREF(func);
return 1; return 1;
} }
if (!is_tupleobject(coerced) || gettuplesize(coerced) != 2) { if (!is_tupleobject(coerced) || gettuplesize(coerced) != 2) {
DECREF(coerced); DECREF(coerced);
DECREF(func); err_setstr(TypeError,
err_setstr(TypeError, "coercion should return None or 2-tuple"); "coercion should return None or 2-tuple");
return -1; return -1;
} }
v1 = gettupleitem(coerced, 0); v1 = gettupleitem(coerced, 0);
w = gettupleitem(coerced, 1);
if (v1 != v) { if (v1 != v) {
v = v1; v = v1;
DECREF(func); if (!is_instanceobject(v) && !is_instanceobject(w)) {
func = getattr(v, opname); if (swapped)
if (func == NULL) { *r_result = (*thisfunc)(w, v);
XDECREF(coerced); else
return -1; *r_result = (*thisfunc)(v, w);
DECREF(coerced);
return *r_result == NULL ? -1 : 0;
} }
} }
w = gettupleitem(coerced, 1); w = gettupleitem(coerced, 1);
} }
func = getattr(v, opname);
if (func == NULL) {
XDECREF(coerced);
if (err_occurred() != AttributeError)
return -1;
err_clear();
return 1;
}
args = mkvalue("(O)", w); args = mkvalue("(O)", w);
if (args == NULL) { if (args == NULL) {
DECREF(func); DECREF(func);
...@@ -1037,6 +1053,7 @@ typedef struct { ...@@ -1037,6 +1053,7 @@ typedef struct {
object *im_func; /* The function implementing the method */ object *im_func; /* The function implementing the method */
object *im_self; /* The instance it is bound to, or NULL */ object *im_self; /* The instance it is bound to, or NULL */
object *im_class; /* The class that defined the method */ object *im_class; /* The class that defined the method */
object *im_doc; /* The documentation string */
} instancemethodobject; } instancemethodobject;
object * object *
...@@ -1059,6 +1076,8 @@ newinstancemethodobject(func, self, class) ...@@ -1059,6 +1076,8 @@ newinstancemethodobject(func, self, class)
im->im_self = self; im->im_self = self;
INCREF(class); INCREF(class);
im->im_class = class; im->im_class = class;
XINCREF(((funcobject *)func)->func_doc);
im->im_doc = ((funcobject *)func)->func_doc;
return (object *)im; return (object *)im;
} }
...@@ -1103,6 +1122,8 @@ static struct memberlist instancemethod_memberlist[] = { ...@@ -1103,6 +1122,8 @@ static struct memberlist instancemethod_memberlist[] = {
{"im_func", T_OBJECT, OFF(im_func)}, {"im_func", T_OBJECT, OFF(im_func)},
{"im_self", T_OBJECT, OFF(im_self)}, {"im_self", T_OBJECT, OFF(im_self)},
{"im_class", T_OBJECT, OFF(im_class)}, {"im_class", T_OBJECT, OFF(im_class)},
{"im_doc", T_OBJECT, OFF(im_doc)},
{"__doc__", T_OBJECT, OFF(im_doc)},
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };
...@@ -1121,6 +1142,7 @@ instancemethod_dealloc(im) ...@@ -1121,6 +1142,7 @@ instancemethod_dealloc(im)
DECREF(im->im_func); DECREF(im->im_func);
XDECREF(im->im_self); XDECREF(im->im_self);
DECREF(im->im_class); DECREF(im->im_class);
XDECREF(im->im_doc);
free((ANY *)im); free((ANY *)im);
} }
......
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