summaryrefslogtreecommitdiffstats
path: root/Objects
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
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')
-rw-r--r--Objects/classobject.c149
-rw-r--r--Objects/dictobject.c152
-rw-r--r--Objects/funcobject.c11
-rw-r--r--Objects/mappingobject.c152
-rw-r--r--Objects/moduleobject.c21
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)