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.)
diff --git a/Python/ceval.c b/Python/ceval.c
index 44239e6..57abda6 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -84,9 +84,10 @@
 static int cmp_member PROTO((object *, object *));
 static object *cmp_outcome PROTO((int, object *, object *));
 static int import_from PROTO((object *, object *, object *));
-static object *build_class PROTO((object *, object *));
+static object *build_class PROTO((object *, object *, object *));
 static void locals_2_fast PROTO((frameobject *, int));
 static void fast_2_locals PROTO((frameobject *));
+static int access_statement PROTO((object *, int, frameobject *));
 
 
 /* Pointer to current frame, used to link new frames to */
@@ -743,10 +744,12 @@
 			break;
 		
 		case BUILD_CLASS:
-			w = POP();
+			u = POP();
 			v = POP();
-			x = build_class(v, w);
+			w = POP();
+			x = build_class(u, v, w);
 			PUSH(x);
+			DECREF(u);
 			DECREF(v);
 			DECREF(w);
 			break;
@@ -754,12 +757,24 @@
 		case STORE_NAME:
 			w = GETNAMEV(oparg);
 			v = POP();
+			u = dict2lookup(f->f_locals, w);
+			if (u != NULL && is_accessobject(u)) {
+				err = setaccessvalue(u, (object *)NULL, v);
+				DECREF(v);
+				break;
+			}
 			err = dict2insert(f->f_locals, w, v);
 			DECREF(v);
 			break;
 		
 		case DELETE_NAME:
 			w = GETNAMEV(oparg);
+			u = dict2lookup(f->f_locals, w);
+			if (u != NULL && is_accessobject(u)) {
+				err = setaccessvalue(u, (object *)NULL,
+						     (object *)NULL);
+				break;
+			}
 			if ((err = dict2remove(f->f_locals, w)) != 0)
 				err_setstr(NameError, getstringvalue(w));
 			break;
@@ -952,12 +967,24 @@
 		case STORE_GLOBAL:
 			w = GETNAMEV(oparg);
 			v = POP();
+			u = dict2lookup(f->f_locals, w);
+			if (u != NULL && is_accessobject(u)) {
+				err = setaccessvalue(u, (object *)NULL, v);
+				DECREF(v);
+				break;
+			}
 			err = dict2insert(f->f_globals, w, v);
 			DECREF(v);
 			break;
 		
 		case DELETE_GLOBAL:
 			w = GETNAMEV(oparg);
+			u = dict2lookup(f->f_locals, w);
+			if (u != NULL && is_accessobject(u)) {
+				err = setaccessvalue(u, (object *)NULL,
+						     (object *)NULL);
+				break;
+			}
 			if ((err = dict2remove(f->f_globals, w)) != 0)
 				err_setstr(NameError, getstringvalue(w));
 			break;
@@ -984,6 +1011,11 @@
 					}
 				}
 			}
+			if (is_accessobject(x)) {
+				x = getaccessvalue(x, (object *)NULL);
+				if (x == NULL)
+					break;
+			}
 			INCREF(x);
 			PUSH(x);
 			break;
@@ -1000,6 +1032,11 @@
 					break;
 				}
 			}
+			if (is_accessobject(x)) {
+				x = getaccessvalue(x, (object *)NULL);
+				if (x == NULL)
+					break;
+			}
 			INCREF(x);
 			PUSH(x);
 			break;
@@ -1011,6 +1048,11 @@
 				err_setstr(NameError, getstringvalue(w));
 				break;
 			}
+			if (is_accessobject(x)) {
+				x = getaccessvalue(x, (object *)NULL);
+				if (x == NULL)
+					break;
+			}
 			INCREF(x);
 			PUSH(x);
 			break;
@@ -1041,15 +1083,25 @@
 					   "undefined local variable");
 				break;
 			}
+			if (is_accessobject(x)) {
+				x = getaccessvalue(x, (object *)NULL);
+				if (x == NULL)
+					break;
+			}
 			INCREF(x);
 			PUSH(x);
 			break;
 
 		case STORE_FAST:
+			v = POP();
 			w = GETLISTITEM(fastlocals, oparg);
+			if (w != NULL && is_accessobject(w)) {
+				err = setaccessvalue(w, (object *)NULL, v);
+				DECREF(v);
+				break;
+			}
 			XDECREF(w);
-			w = POP();
-			GETLISTITEM(fastlocals, oparg) = w;
+			GETLISTITEM(fastlocals, oparg) = v;
 			break;
 
 		case DELETE_FAST:
@@ -1059,6 +1111,11 @@
 					   "undefined local variable");
 				break;
 			}
+			if (w != NULL && is_accessobject(w)) {
+				err = setaccessvalue(w, (object *)NULL,
+						     (object *)NULL);
+				break;
+			}
 			DECREF(x);
 			GETLISTITEM(fastlocals, oparg) = NULL;
 			break;
@@ -1124,6 +1181,13 @@
 			err = import_from(f->f_locals, v, w);
 			locals_2_fast(f, 0);
 			break;
+
+		case ACCESS_MODE:
+			v = POP();
+			w = GETNAMEV(oparg);
+			err = access_statement(w, (int)getintvalue(v), f);
+			DECREF(v);
+			break;
 		
 		case JUMP_FORWARD:
 			JUMPBY(oparg);
@@ -1483,7 +1547,8 @@
 	/* Merge f->f_fastlocals into f->f_locals */
 	object *locals, *fast, *map;
 	object *error_type, *error_value;
-	int i;
+	int pos;
+	object *key, *value;
 	if (f == NULL)
 		return;
 	locals = f->f_locals;
@@ -1495,16 +1560,10 @@
 	    !is_dictobject(map))
 		return;
 	err_get(&error_type, &error_value);
-	i = getdictsize(map);
-	while (--i >= 0) {
-		object *key;
-		object *value;
+	pos = 0;
+	while (mappinggetnext(map, &pos, &key, &value)) {
 		int j;
-		key = getdict2key(map, i);
-		if (key == NULL)
-			continue;
-		value = dict2lookup(map, key);
-		if (value == NULL || !is_intobject(value))
+		if (!is_intobject(value))
 			continue;
 		j = getintvalue(value);
 		value = getlistitem(fast, j);
@@ -1529,7 +1588,8 @@
 	/* Merge f->f_locals into f->f_fastlocals */
 	object *locals, *fast, *map;
 	object *error_type, *error_value;
-	int i;
+	int pos;
+	object *key, *value;
 	if (f == NULL)
 		return;
 	locals = f->f_locals;
@@ -1541,16 +1601,10 @@
 	    !is_dictobject(map))
 		return;
 	err_get(&error_type, &error_value);
-	i = getdictsize(map);
-	while (--i >= 0) {
-		object *key;
-		object *value;
+	pos = 0;
+	while (mappinggetnext(map, &pos, &key, &value)) {
 		int j;
-		key = getdict2key(map, i);
-		if (key == NULL)
-			continue;
-		value = dict2lookup(map, key);
-		if (value == NULL || !is_intobject(value))
+		if (!is_intobject(value))
 			continue;
 		j = getintvalue(value);
 		value = dict2lookup(locals, key);
@@ -1907,14 +1961,7 @@
 		return (*meth)(self, arg);
 	}
 	if (is_classobject(func)) {
-		if (arg != NULL &&
-				!(is_tupleobject(arg) &&
-					gettuplesize(arg) == 0)) {
-			err_setstr(TypeError,
-				"classobject() allows no arguments");
-			return NULL;
-		}
-		return newinstanceobject(func);
+		return newinstanceobject(func, arg);
 	}
 	err_setstr(TypeError, "call of non-function");
 	return NULL;
@@ -2258,19 +2305,14 @@
 	object *w, *x;
 	w = getmoduledict(v);
 	if (getstringvalue(name)[0] == '*') {
-		int i;
-		int n = getdictsize(w);
-		for (i = 0; i < n; i++) {
-			name = getdict2key(w, i);
-			if (name == NULL || getstringvalue(name)[0] == '_')
+		int pos;
+		object *name, *value;
+		pos = 0;
+		while (mappinggetnext(w, &pos, &name, &value)) {
+			if (!is_stringobject(name) ||
+			    getstringvalue(name)[0] == '_')
 				continue;
-			x = dict2lookup(w, name);
-			if (x == NULL) {
-				/* XXX can't happen? */
-				err_setstr(SystemError, getstringvalue(name));
-				return -1;
-			}
-			if (dict2insert(locals, name, x) != 0)
+			if (dict2insert(locals, name, value) != 0)
 				return -1;
 		}
 		return 0;
@@ -2290,27 +2332,74 @@
 }
 
 static object *
-build_class(v, w)
-	object *v; /* None or tuple containing base classes */
-	object *w; /* dictionary */
+build_class(methods, bases, name)
+	object *methods; /* dictionary */
+	object *bases;  /* tuple containing classes */
+	object *name;   /* string */
 {
-	if (is_tupleobject(v)) {
-		int i;
-		for (i = gettuplesize(v); --i >= 0; ) {
-			object *x = gettupleitem(v, i);
-			if (!is_classobject(x)) {
-				err_setstr(TypeError,
-					"base is not a class object");
-				return NULL;
-			}
-		}
+	int i;
+	if (!is_tupleobject(bases)) {
+		err_setstr(SystemError, "build_class with non-tuple bases");
+		return NULL;
 	}
-	else {
-		v = NULL;
-	}
-	if (!is_dictobject(w)) {
+	if (!is_dictobject(methods)) {
 		err_setstr(SystemError, "build_class with non-dictionary");
 		return NULL;
 	}
-	return newclassobject(v, w, (object *) NULL);
+	if (!is_stringobject(name)) {
+		err_setstr(SystemError, "build_class witn non-string name");
+		return NULL;
+	}
+	for (i = gettuplesize(bases); --i >= 0; ) {
+		object *base = gettupleitem(bases, i);
+		if (!is_classobject(base)) {
+			err_setstr(TypeError,
+				"base is not a class object");
+			return NULL;
+		}
+	}
+	return newclassobject(bases, methods, name);
+}
+
+static int
+access_statement(name, mode, f)
+	object *name;
+	int mode;
+	frameobject *f;
+{
+	object *value;
+	int i = -1;
+	object *ac;
+	int ret;
+	if (f->f_localmap == NULL)
+		value = dict2lookup(f->f_locals, name);
+	else {
+		value = dict2lookup(f->f_localmap, name);
+		if (value == NULL || !is_intobject(value))
+			value = NULL;
+		else {
+			i = getintvalue(value);
+			if (0 <= i && i < getlistsize(f->f_fastlocals))
+				value = getlistitem(f->f_fastlocals, i);
+			else {
+				value = NULL;
+				i = -1;
+			}
+		}
+	}
+	if (value && is_accessobject(value)) {
+		err_setstr(AccessError, "can't override access");
+		return -1;
+	}
+	err_clear();
+	ac = newaccessobject(value, (object*)NULL, (typeobject*)NULL, mode);
+	if (ac == NULL)
+		return -1;
+	if (i >= 0)
+		ret = setlistitem(f->f_fastlocals, i, ac);
+	else {
+		ret = dict2insert(f->f_locals, name, ac);
+		DECREF(ac);
+	}
+	return ret;
 }