summaryrefslogtreecommitdiffstats
path: root/Objects/classobject.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1993-05-19 14:50:45 (GMT)
committerGuido van Rossum <guido@python.org>1993-05-19 14:50:45 (GMT)
commit25831652fd4c03323066d4cafdc0551c396a993e (patch)
tree69588df0f98b3280402cad3ed95865d06fa21702 /Objects/classobject.c
parent687dd13bfec51849c93db7c538ff41d4c8ecddcb (diff)
downloadcpython-25831652fd4c03323066d4cafdc0551c396a993e.zip
cpython-25831652fd4c03323066d4cafdc0551c396a993e.tar.gz
cpython-25831652fd4c03323066d4cafdc0551c396a993e.tar.bz2
Several changes in one:
(1) dictionaries/mappings now have attributes values() and items() as well as keys(); at the C level, use the new function mappinggetnext() to iterate over a dictionary. (2) "class C(): ..." is now illegal; you must write "class C: ...". (3) Class objects now know their own name (finally!); and minor improvements to the way how classes, functions and methods are represented as strings. (4) Added an "access" statement and semantics. (This is still experimental -- as long as you don't use the keyword 'access' nothing should be changed.)
Diffstat (limited to 'Objects/classobject.c')
-rw-r--r--Objects/classobject.c149
1 files changed, 136 insertions, 13 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 587d122..bc61b64 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -29,9 +29,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "structmember.h"
#include "ceval.h"
-extern typeobject MappingInstancetype;
-extern typeobject SequenceInstancetype;
-
typedef struct {
OB_HEAD
object *cl_bases; /* A tuple */
@@ -102,7 +99,10 @@ class_getattr(op, name)
}
v = dictlookup(op->cl_methods, name);
if (v != NULL) {
- INCREF(v);
+ if (is_accessobject(v))
+ v = getaccessvalue(v, (object *)NULL);
+ else
+ INCREF(v);
return v;
}
{
@@ -126,6 +126,7 @@ class_setattr(op, name, v)
char *name;
object *v;
{
+ object *ac;
if (name[0] == '_' && name[1] == '_') {
int n = strlen(name);
if (name[n-1] == '_' && name[n-2] == '_') {
@@ -133,6 +134,9 @@ class_setattr(op, name, v)
return -1;
}
}
+ ac = dictlookup(op->cl_methods, name);
+ if (ac != NULL && is_accessobject(ac))
+ return setaccessvalue(ac, (object *)NULL, v);
if (v == NULL) {
int rv = dictremove(op->cl_methods, name);
if (rv < 0)
@@ -144,6 +148,20 @@ class_setattr(op, name, v)
return dictinsert(op->cl_methods, name, v);
}
+static object *
+class_repr(op)
+ classobject *op;
+{
+ char buf[140];
+ char *name;
+ if (op->cl_name == NULL || !is_stringobject(op->cl_name))
+ name = "?";
+ else
+ name = getstringvalue(op->cl_name);
+ sprintf(buf, "<class %.100s at %lx>", name, (long)op);
+ return newstringobject(buf);
+}
+
typeobject Classtype = {
OB_HEAD_INIT(&Typetype)
0,
@@ -155,7 +173,7 @@ typeobject Classtype = {
class_getattr, /*tp_getattr*/
class_setattr, /*tp_setattr*/
0, /*tp_compare*/
- 0, /*tp_repr*/
+ class_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
@@ -170,12 +188,18 @@ typedef struct {
object *in_attr; /* A dictionary */
} instanceobject;
+static object *instance_getattr PROTO((instanceobject *, char *));
+
object *
-newinstanceobject(class)
- register object *class;
+newinstanceobject(class, arg)
+ object *class;
+ object *arg;
{
register instanceobject *inst;
object *v;
+ object *init;
+ int pos;
+ object *key, *value;
if (!is_classobject(class)) {
err_badcall();
return NULL;
@@ -187,9 +211,52 @@ newinstanceobject(class)
inst->in_class = (classobject *)class;
inst->in_attr = newdictobject();
if (inst->in_attr == NULL) {
+ error:
DECREF(inst);
return NULL;
}
+ pos = 0;
+ while (mappinggetnext(((classobject *)class)->cl_methods,
+ &pos, &key, &value)) {
+ if (is_accessobject(value)) {
+ object *ac = cloneaccessobject(value);
+ int err;
+ if (ac == NULL)
+ goto error;
+ err = dict2insert(inst->in_attr, key, ac);
+ DECREF(ac);
+ if (err)
+ goto error;
+ }
+ }
+ init = instance_getattr(inst, "__init__");
+ if (init == NULL) {
+ err_clear();
+ if (arg != NULL && !(is_tupleobject(arg) &&
+ gettuplesize(arg) == 0)) {
+ err_setstr(TypeError,
+ "this classobject() takes no arguments");
+ DECREF(inst);
+ inst = NULL;
+ }
+ }
+ else {
+ object *res = call_object(init, arg);
+ DECREF(init);
+ if (res == NULL) {
+ DECREF(inst);
+ inst = NULL;
+ }
+ else {
+ if (res != None) {
+ err_setstr(TypeError,
+ "__init__() should return None");
+ DECREF(inst);
+ inst = NULL;
+ }
+ DECREF(res);
+ }
+ }
return (object *)inst;
}
@@ -199,9 +266,29 @@ static void
instance_dealloc(inst)
register instanceobject *inst;
{
+ object *error_type, *error_value;
+ object *del;
+ /* Call the __del__ method if it exists. First temporarily
+ revive the object and save the current exception, if any. */
+ INCREF(inst);
+ err_get(&error_type, &error_value);
+ if ((del = instance_getattr(inst, "__del__")) != NULL) {
+ object *args = newtupleobject(0);
+ object *res = args;
+ if (res != NULL)
+ res = call_object(del, args);
+ XDECREF(args);
+ DECREF(del);
+ XDECREF(res);
+ /* XXX If __del__ raised an exception, it is ignored! */
+ }
+ /* Restore the saved exception and undo the temporary revival */
+ err_setval(error_type, error_value);
+ /* Can't use DECREF here, it would cause a recursive call */
+ if (--inst->ob_refcnt > 0)
+ return; /* __del__ added a reference; don't delete now */
DECREF(inst->in_class);
- if (inst->in_attr != NULL)
- DECREF(inst->in_attr);
+ XDECREF(inst->in_attr);
free((ANY *)inst);
}
@@ -221,7 +308,10 @@ instance_getattr(inst, name)
}
v = dictlookup(inst->in_attr, name);
if (v != NULL) {
- INCREF(v);
+ if (is_accessobject(v))
+ v = getaccessvalue(v, (object *)NULL);
+ else
+ INCREF(v);
return v;
}
v = class_getattr(inst->in_class, name);
@@ -243,6 +333,7 @@ instance_setattr(inst, name, v)
char *name;
object *v;
{
+ object *ac;
if (name[0] == '_' && name[1] == '_') {
int n = strlen(name);
if (name[n-1] == '_' && name[n-2] == '_') {
@@ -250,6 +341,9 @@ instance_setattr(inst, name, v)
return -1;
}
}
+ ac = dictlookup(inst->in_attr, name);
+ if (ac != NULL && is_accessobject(ac))
+ return setaccessvalue(ac, (object *)NULL, v);
if (v == NULL) {
int rv = dictremove(inst->in_attr, name);
if (rv < 0)
@@ -270,9 +364,15 @@ instance_repr(inst)
func = instance_getattr(inst, "__repr__");
if (func == NULL) {
- char buf[80];
+ char buf[140];
+ object *classname = inst->in_class->cl_name;
+ char *cname;
+ if (classname != NULL && is_stringobject(classname))
+ cname = getstringvalue(classname);
+ else
+ cname = "?";
err_clear();
- sprintf(buf, "<instance object at %lx>", (long)inst);
+ sprintf(buf, "<%.100s instance at %lx>", cname, (long)inst);
return newstringobject(buf);
}
res = call_object(func, (object *)NULL);
@@ -773,6 +873,7 @@ typeobject Instancetype = {
0,
instance_dealloc, /*tp_dealloc*/
0, /*tp_print*/
+ (object * (*) FPROTO((object *, char *)))
instance_getattr, /*tp_getattr*/
instance_setattr, /*tp_setattr*/
instance_compare, /*tp_compare*/
@@ -879,6 +980,28 @@ instancemethod_compare(a, b)
return cmp;
}
+static object *
+instancemethod_repr(a)
+ instancemethodobject *a;
+{
+ char buf[240];
+ object *classname =
+ ((instanceobject *)(a->im_self))->in_class->cl_name;
+ object *funcname = ((funcobject *)(a->im_func))->func_name;
+ char *cname, *fname;
+ if (classname != NULL && is_stringobject(classname))
+ cname = getstringvalue(classname);
+ else
+ cname = "?";
+ if (funcname != NULL && is_stringobject(funcname))
+ fname = getstringvalue(funcname);
+ else
+ fname = "?";
+ sprintf(buf, "<method %.100s of %.100s instance at %lx>",
+ fname, cname, (long)a->im_func);
+ return newstringobject(buf);
+}
+
static long
instancemethod_hash(a)
instancemethodobject *a;
@@ -904,7 +1027,7 @@ typeobject Instancemethodtype = {
instancemethod_getattr, /*tp_getattr*/
0, /*tp_setattr*/
instancemethod_compare, /*tp_compare*/
- 0, /*tp_repr*/
+ instancemethod_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/