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 | |
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')
-rw-r--r-- | Objects/classobject.c | 149 | ||||
-rw-r--r-- | Objects/dictobject.c | 152 | ||||
-rw-r--r-- | Objects/funcobject.c | 11 | ||||
-rw-r--r-- | Objects/mappingobject.c | 152 | ||||
-rw-r--r-- | Objects/moduleobject.c | 21 |
5 files changed, 386 insertions, 99 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*/ diff --git a/Objects/dictobject.c b/Objects/dictobject.c index fa66a9d..c50b35a 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -307,39 +307,49 @@ mappingremove(op, key) return 0; } -int -getmappingsize(op) - register object *op; +void +mappingclear(op) + object *op; { - if (!is_mappingobject(op)) { - err_badcall(); - return -1; + int i; + register mappingobject *mp; + if (!is_mappingobject(op)) + return; + mp = (mappingobject *)op; + for (i = 0; i < mp->ma_size; i++) { + XDECREF(mp->ma_table[i].me_key); + XDECREF(mp->ma_table[i].me_value); + mp->ma_table[i].me_key = NULL; + mp->ma_table[i].me_value = NULL; } - return ((mappingobject *)op) -> ma_size; + mp->ma_used = 0; } -object * -getmappingkey(op, i) +int +mappinggetnext(op, ppos, pkey, pvalue) object *op; - register int i; + int *ppos; + object **pkey; + object **pvalue; { - /* XXX This can't return errors since its callers assume - that NULL means there was no key at that point */ + int i; register mappingobject *mp; - if (!is_mappingobject(op)) { - /* err_badcall(); */ - return NULL; - } + if (!is_dictobject(op)) + return 0; mp = (mappingobject *)op; - if (i < 0 || i >= mp->ma_size) { - /* err_badarg(); */ - return NULL; - } - if (mp->ma_table[i].me_value == NULL) { - /* Not an error! */ - return NULL; - } - return (object *) mp->ma_table[i].me_key; + i = *ppos; + if (i < 0) + return 0; + while (i < mp->ma_size && mp->ma_table[i].me_value == NULL) + i++; + *ppos = i+1; + if (i >= mp->ma_size) + return 0; + if (pkey) + *pkey = mp->ma_table[i].me_key; + if (pvalue) + *pvalue = mp->ma_table[i].me_value; + return 1; } /* Methods */ @@ -488,6 +498,61 @@ mapping_keys(mp, args) return v; } +static object * +mapping_values(mp, args) + register mappingobject *mp; + object *args; +{ + register object *v; + register int i, j; + if (!getnoarg(args)) + return NULL; + v = newlistobject(mp->ma_used); + if (v == NULL) + return NULL; + for (i = 0, j = 0; i < mp->ma_size; i++) { + if (mp->ma_table[i].me_value != NULL) { + object *value = mp->ma_table[i].me_value; + INCREF(value); + setlistitem(v, j, value); + j++; + } + } + return v; +} + +static object * +mapping_items(mp, args) + register mappingobject *mp; + object *args; +{ + register object *v; + register int i, j; + if (!getnoarg(args)) + return NULL; + v = newlistobject(mp->ma_used); + if (v == NULL) + return NULL; + for (i = 0, j = 0; i < mp->ma_size; i++) { + if (mp->ma_table[i].me_value != NULL) { + object *key = mp->ma_table[i].me_key; + object *value = mp->ma_table[i].me_value; + object *item = newtupleobject(2); + if (item == NULL) { + DECREF(v); + return NULL; + } + INCREF(key); + settupleitem(item, 0, key); + INCREF(value); + settupleitem(item, 1, value); + setlistitem(v, j, item); + j++; + } + } + return v; +} + object * getmappingkeys(mp) object *mp; @@ -499,6 +564,28 @@ getmappingkeys(mp) return mapping_keys((mappingobject *)mp, (object *)NULL); } +object * +getmappingvalues(mp) + object *mp; +{ + if (mp == NULL || !is_mappingobject(mp)) { + err_badcall(); + return NULL; + } + return mapping_values((mappingobject *)mp, (object *)NULL); +} + +object * +getmappingitems(mp) + object *mp; +{ + if (mp == NULL || !is_mappingobject(mp)) { + err_badcall(); + return NULL; + } + return mapping_values((mappingobject *)mp, (object *)NULL); +} + static int mapping_compare(a, b) mappingobject *a, *b; @@ -582,8 +669,10 @@ mapping_has_key(mp, args) } static struct methodlist mapp_methods[] = { - {"keys", mapping_keys}, {"has_key", mapping_has_key}, + {"items", mapping_items}, + {"keys", mapping_keys}, + {"values", mapping_values}, {NULL, NULL} /* sentinel */ }; @@ -697,14 +786,3 @@ dictremove(v, key) } return mappingremove(v, last_name_object); } - -char * -getdictkey(v, i) - object *v; - int i; -{ - object *key = getmappingkey(v, i); - if (key == NULL) - return NULL; - return getstringvalue(key); -} diff --git a/Objects/funcobject.c b/Objects/funcobject.c index ccf1b29..cf08af7 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -28,12 +28,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "compile.h" #include "structmember.h" -typedef struct { - OB_HEAD - object *func_code; - object *func_globals; -} funcobject; - object * newfuncobject(code, globals) object *code; @@ -45,6 +39,8 @@ newfuncobject(code, globals) op->func_code = code; INCREF(globals); op->func_globals = globals; + op->func_name = ((codeobject*)(op->func_code))->co_name; + INCREF(op->func_name); } return (object *)op; } @@ -78,6 +74,7 @@ getfuncglobals(op) static struct memberlist func_memberlist[] = { {"func_code", T_OBJECT, OFF(func_code), READONLY}, {"func_globals",T_OBJECT, OFF(func_globals), READONLY}, + {"func_name", T_OBJECT, OFF(func_name), READONLY}, {NULL} /* Sentinel */ }; @@ -104,7 +101,7 @@ func_repr(op) { char buf[140]; sprintf(buf, "<function %.100s at %lx>", - getstringvalue(((codeobject*)(op->func_code))->co_name), + getstringvalue(op->func_name), (long)op); return newstringobject(buf); } diff --git a/Objects/mappingobject.c b/Objects/mappingobject.c index fa66a9d..c50b35a 100644 --- a/Objects/mappingobject.c +++ b/Objects/mappingobject.c @@ -307,39 +307,49 @@ mappingremove(op, key) return 0; } -int -getmappingsize(op) - register object *op; +void +mappingclear(op) + object *op; { - if (!is_mappingobject(op)) { - err_badcall(); - return -1; + int i; + register mappingobject *mp; + if (!is_mappingobject(op)) + return; + mp = (mappingobject *)op; + for (i = 0; i < mp->ma_size; i++) { + XDECREF(mp->ma_table[i].me_key); + XDECREF(mp->ma_table[i].me_value); + mp->ma_table[i].me_key = NULL; + mp->ma_table[i].me_value = NULL; } - return ((mappingobject *)op) -> ma_size; + mp->ma_used = 0; } -object * -getmappingkey(op, i) +int +mappinggetnext(op, ppos, pkey, pvalue) object *op; - register int i; + int *ppos; + object **pkey; + object **pvalue; { - /* XXX This can't return errors since its callers assume - that NULL means there was no key at that point */ + int i; register mappingobject *mp; - if (!is_mappingobject(op)) { - /* err_badcall(); */ - return NULL; - } + if (!is_dictobject(op)) + return 0; mp = (mappingobject *)op; - if (i < 0 || i >= mp->ma_size) { - /* err_badarg(); */ - return NULL; - } - if (mp->ma_table[i].me_value == NULL) { - /* Not an error! */ - return NULL; - } - return (object *) mp->ma_table[i].me_key; + i = *ppos; + if (i < 0) + return 0; + while (i < mp->ma_size && mp->ma_table[i].me_value == NULL) + i++; + *ppos = i+1; + if (i >= mp->ma_size) + return 0; + if (pkey) + *pkey = mp->ma_table[i].me_key; + if (pvalue) + *pvalue = mp->ma_table[i].me_value; + return 1; } /* Methods */ @@ -488,6 +498,61 @@ mapping_keys(mp, args) return v; } +static object * +mapping_values(mp, args) + register mappingobject *mp; + object *args; +{ + register object *v; + register int i, j; + if (!getnoarg(args)) + return NULL; + v = newlistobject(mp->ma_used); + if (v == NULL) + return NULL; + for (i = 0, j = 0; i < mp->ma_size; i++) { + if (mp->ma_table[i].me_value != NULL) { + object *value = mp->ma_table[i].me_value; + INCREF(value); + setlistitem(v, j, value); + j++; + } + } + return v; +} + +static object * +mapping_items(mp, args) + register mappingobject *mp; + object *args; +{ + register object *v; + register int i, j; + if (!getnoarg(args)) + return NULL; + v = newlistobject(mp->ma_used); + if (v == NULL) + return NULL; + for (i = 0, j = 0; i < mp->ma_size; i++) { + if (mp->ma_table[i].me_value != NULL) { + object *key = mp->ma_table[i].me_key; + object *value = mp->ma_table[i].me_value; + object *item = newtupleobject(2); + if (item == NULL) { + DECREF(v); + return NULL; + } + INCREF(key); + settupleitem(item, 0, key); + INCREF(value); + settupleitem(item, 1, value); + setlistitem(v, j, item); + j++; + } + } + return v; +} + object * getmappingkeys(mp) object *mp; @@ -499,6 +564,28 @@ getmappingkeys(mp) return mapping_keys((mappingobject *)mp, (object *)NULL); } +object * +getmappingvalues(mp) + object *mp; +{ + if (mp == NULL || !is_mappingobject(mp)) { + err_badcall(); + return NULL; + } + return mapping_values((mappingobject *)mp, (object *)NULL); +} + +object * +getmappingitems(mp) + object *mp; +{ + if (mp == NULL || !is_mappingobject(mp)) { + err_badcall(); + return NULL; + } + return mapping_values((mappingobject *)mp, (object *)NULL); +} + static int mapping_compare(a, b) mappingobject *a, *b; @@ -582,8 +669,10 @@ mapping_has_key(mp, args) } static struct methodlist mapp_methods[] = { - {"keys", mapping_keys}, {"has_key", mapping_has_key}, + {"items", mapping_items}, + {"keys", mapping_keys}, + {"values", mapping_values}, {NULL, NULL} /* sentinel */ }; @@ -697,14 +786,3 @@ dictremove(v, key) } return mappingremove(v, last_name_object); } - -char * -getdictkey(v, i) - object *v; - int i; -{ - object *key = getmappingkey(v, i); - if (key == NULL) - return NULL; - return getstringvalue(key); -} diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 749d872..8949c7d 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -109,8 +109,12 @@ module_getattr(m, name) res = dictlookup(m->md_dict, name); if (res == NULL) err_setstr(AttributeError, name); - else - INCREF(res); + else { + if (is_accessobject(res)) + res = getaccessvalue(res, (object *)NULL); + else + INCREF(res); + } return res; } @@ -120,10 +124,17 @@ module_setattr(m, name, v) char *name; object *v; { - if (strcmp(name, "__dict__") == 0 || strcmp(name, "__name__") == 0) { - err_setstr(TypeError, "read-only special attribute"); - return -1; + object *ac; + if (name[0] == '_' && name[1] == '_') { + int n = strlen(name); + if (name[n-1] == '_' && name[n-2] == '_') { + err_setstr(TypeError, "read-only special attribute"); + return -1; + } } + ac = dictlookup(m->md_dict, name); + if (ac != NULL && is_accessobject(ac)) + return setaccessvalue(ac, (object *)NULL, v); if (v == NULL) { int rv = dictremove(m->md_dict, name); if (rv < 0) |