diff options
author | Guido van Rossum <guido@python.org> | 1993-05-19 14:50:45 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1993-05-19 14:50:45 (GMT) |
commit | 25831652fd4c03323066d4cafdc0551c396a993e (patch) | |
tree | 69588df0f98b3280402cad3ed95865d06fa21702 /Objects/classobject.c | |
parent | 687dd13bfec51849c93db7c538ff41d4c8ecddcb (diff) | |
download | cpython-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.c | 149 |
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*/ |