Kaydet (Commit) b3f7258f authored tarafından Guido van Rossum's avatar Guido van Rossum

* Lots of small changes related to access.

* Added "access *: ...", made access work for class methods.
* Introduced subclass check: make sure that when calling
  ClassName.methodname(instance, ...), the instance is an instance of
  ClassName or of a subclass thereof (this might break some old code!)
üst 81daa32c
......@@ -100,7 +100,7 @@ return_stmt: 'return' [testlist]
raise_stmt: 'raise' test [',' test]
import_stmt: 'import' NAME (',' NAME)* | 'from' NAME 'import' ('*' | NAME (',' NAME)*)
global_stmt: 'global' NAME (',' NAME)*
access_stmt: 'access' NAME (',' NAME)* ':' accesstype (',' accesstype)*
access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)*
accesstype: NAME+
# accesstype should be ('public' | 'protected' | 'private') ['read'] ['write']
# but can't be because that would create undesirable reserved words!
......
......@@ -50,5 +50,6 @@ int setaccessvalue PROTO((object *, object *, object *));
void setaccessowner PROTO((object *, object *));
object *cloneaccessobject PROTO((object *));
int hasaccessvalue PROTO((object *));
extern typeobject Anynumbertype, Anysequencetype, Anymappingtype;
......@@ -24,11 +24,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* Class object interface */
/*
Classes are really hacked in at the last moment.
It should be possible to use other object types as base classes,
but currently it isn't. We'll see if we can fix that later, sigh...
*/
/* Revealing some structures (not for general use) */
typedef struct {
OB_HEAD
......@@ -37,6 +33,12 @@ typedef struct {
object *cl_name; /* A string */
} classobject;
typedef struct {
OB_HEAD
classobject *in_class; /* The class object */
object *in_dict; /* A dictionary */
} instanceobject;
extern typeobject Classtype, Instancetype, Instancemethodtype;
#define is_classobject(op) ((op)->ob_type == &Classtype)
......
......@@ -99,6 +99,15 @@ setaccessowner(op, class)
ap->ac_class = class;
}
int
hasaccessvalue(op)
object *op;
{
if (!is_accessobject(op))
return 0;
return ((accessobject *)op)->ac_value != NULL;
}
object *
getaccessvalue(op, class)
object *op;
......@@ -268,7 +277,9 @@ access_repr(ap)
char buf[300];
classobject *class = (classobject *)ap->ac_class;
typeobject *type = ap->ac_type;
sprintf(buf, "<access object, class %.100s, type %.100s, mode 0%o>",
sprintf(buf,
"<access object, value 0x%lx, class %.100s, type %.100s, mode %04o>",
(long)(ap->ac_value),
class ? getstringvalue(class->cl_name) : "-",
type ? type->tp_name : "-",
ap->ac_mode);
......
......@@ -121,18 +121,24 @@ class_getattr(op, name)
return v;
}
v = class_lookup(op, name, &class);
if (v != NULL) {
if (is_accessobject(v))
v = getaccessvalue(v, getclass());
else if (is_funcobject(v))
v = newinstancemethodobject(v, (object *)NULL,
if (v == NULL) {
err_setstr(AttributeError, name);
return NULL;
}
if (is_accessobject(v)) {
v = getaccessvalue(v, getclass());
if (v == NULL)
return NULL;
}
else
INCREF(v);
if (is_funcobject(v)) {
object *w = newinstancemethodobject(v, (object *)NULL,
(object *)class);
else
INCREF(v);
return v;
DECREF(v);
v = w;
}
err_setstr(AttributeError, name);
return NULL;
return v;
}
static int
......@@ -217,12 +223,6 @@ issubclass(class, base)
/* Instance objects */
typedef struct {
OB_HEAD
classobject *in_class; /* The class object */
object *in_dict; /* A dictionary */
} instanceobject;
static object *instance_getattr PROTO((instanceobject *, char *));
static int
......@@ -241,8 +241,11 @@ addaccess(class, inst)
pos = 0;
while (mappinggetnext(class->cl_dict, &pos, &key, &value)) {
object *v;
if (!is_accessobject(value))
continue;
if (hasaccessvalue(value))
continue;
ac = dict2lookup(inst->in_dict, key);
if (ac != NULL && is_accessobject(ac)) {
err_setval(ConflictError, key);
......@@ -361,22 +364,27 @@ instance_getattr(inst, name)
return (object *)inst->in_class;
}
v = dictlookup(inst->in_dict, name);
if (v != NULL) {
if (is_accessobject(v))
v = getaccessvalue(v, getclass());
else
INCREF(v);
return v;
if (v == NULL) {
v = class_lookup(inst->in_class, name, &class);
if (v == NULL) {
err_setstr(AttributeError, name);
return NULL;
}
}
v = class_lookup(inst->in_class, name, &class);
if (v == NULL)
goto error;
if (is_funcobject(v))
return newinstancemethodobject(v, (object *)inst,
(object *)class);
error:
err_setstr(AttributeError, name);
return NULL;
if (is_accessobject(v)) {
v = getaccessvalue(v, getclass());
if (v == NULL)
return NULL;
}
else
INCREF(v);
if (is_funcobject(v)) {
object *w = newinstancemethodobject(v, (object *)inst,
(object *)class);
DECREF(v);
v = w;
}
return v;
}
static int
......
......@@ -105,10 +105,10 @@ meth_repr(m)
{
char buf[200];
if (m->m_self == NULL)
sprintf(buf, "<built-in function '%.80s'>", m->m_name);
sprintf(buf, "<built-in function %.80s>", m->m_name);
else
sprintf(buf,
"<built-in method '%.80s' of %.80s object at %lx>",
"<built-in method %.80s of %.80s object at %lx>",
m->m_name, m->m_self->ob_type->tp_name,
(long)m->m_self);
return newstringobject(buf);
......
......@@ -87,7 +87,7 @@ static int import_from PROTO((object *, 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 *));
static int access_statement PROTO((object *, object *, frameobject *));
/* Pointer to current frame, used to link new frames to */
......@@ -184,7 +184,8 @@ eval_code(co, globals, locals, class, arg)
object *trace = NULL; /* Trace function or NULL */
object *retval; /* Return value iff why == WHY_RETURN */
char *name; /* Name used by some instructions */
int needmerge = 0;
int needmerge = 0; /* Set if need to merge locals back at end */
int defmode = 0; /* Default access mode for new variables */
#ifdef LLTRACE
int lltrace;
#endif
......@@ -760,7 +761,22 @@ eval_code(co, globals, locals, class, arg)
w = GETNAMEV(oparg);
v = POP();
u = dict2lookup(f->f_locals, w);
if (u != NULL && is_accessobject(u)) {
if (u == NULL) {
if (defmode != 0) {
if (v != None)
u = (object *)v->ob_type;
else
u = NULL;
x = newaccessobject(v, class,
(typeobject *)u,
defmode);
DECREF(v);
if (x == NULL)
break;
v = x;
}
}
else if (is_accessobject(u)) {
err = setaccessvalue(u, class, v);
DECREF(v);
break;
......@@ -1190,7 +1206,10 @@ eval_code(co, globals, locals, class, arg)
case ACCESS_MODE:
v = POP();
w = GETNAMEV(oparg);
err = access_statement(w, (int)getintvalue(v), f);
if (getstringvalue(w)[0] == '*')
defmode = getintvalue(v);
else
err = access_statement(w, v, f);
DECREF(v);
break;
......@@ -1995,7 +2014,28 @@ call_function(func, arg)
object *self = instancemethodgetself(func);
class = instancemethodgetclass(func);
func = instancemethodgetfunc(func);
if (self != NULL) {
if (self == NULL) {
/* Unbound methods must be called with an instance of
the class (or a derived class) as first argument */
if (arg != NULL && is_tupleobject(arg) &&
gettuplesize(arg) >= 1) {
self = gettupleitem(arg, 0);
if (self != NULL &&
is_instanceobject(self) &&
issubclass((object *)
(((instanceobject *)self)->in_class),
class))
/* self = self */ ;
else
self = NULL;
}
if (self == NULL) {
err_setstr(TypeError,
"unbound method must be called with class instance argument");
return NULL;
}
}
else {
int argcount;
if (arg == NULL)
argcount = 0;
......@@ -2380,11 +2420,12 @@ build_class(methods, bases, name)
}
static int
access_statement(name, mode, f)
access_statement(name, vmode, f)
object *name;
int mode;
object *vmode;
frameobject *f;
{
int mode = getintvalue(vmode);
object *value, *ac;
typeobject *type;
int fastind, ret;
......@@ -2415,7 +2456,7 @@ access_statement(name, mode, f)
type = value->ob_type;
else
type = NULL;
ac = newaccessobject(value, (object*)NULL, type, mode);
ac = newaccessobject(value, f->f_class, type, mode);
if (ac == NULL)
return -1;
if (fastind >= 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment