mirror of
https://github.com/python/cpython.git
synced 2025-10-17 04:08:28 +00:00
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.)
This commit is contained in:
parent
687dd13bfe
commit
25831652fd
21 changed files with 1223 additions and 823 deletions
|
@ -796,7 +796,9 @@ getbuiltin(name)
|
|||
|
||||
/* Predefined exceptions */
|
||||
|
||||
object *AccessError;
|
||||
object *AttributeError;
|
||||
object *ConflictError;
|
||||
object *EOFError;
|
||||
object *IOError;
|
||||
object *ImportError;
|
||||
|
@ -827,7 +829,9 @@ newstdexception(name)
|
|||
static void
|
||||
initerrors()
|
||||
{
|
||||
AccessError = newstdexception("AccessError");
|
||||
AttributeError = newstdexception("AttributeError");
|
||||
ConflictError = newstdexception("ConflictError");
|
||||
EOFError = newstdexception("EOFError");
|
||||
IOError = newstdexception("IOError");
|
||||
ImportError = newstdexception("ImportError");
|
||||
|
|
215
Python/ceval.c
215
Python/ceval.c
|
@ -84,9 +84,10 @@ static int cmp_exception PROTO((object *, object *));
|
|||
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 @@ eval_code(co, globals, locals, arg)
|
|||
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 @@ eval_code(co, globals, locals, arg)
|
|||
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 @@ eval_code(co, globals, locals, arg)
|
|||
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 @@ eval_code(co, globals, locals, arg)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (is_accessobject(x)) {
|
||||
x = getaccessvalue(x, (object *)NULL);
|
||||
if (x == NULL)
|
||||
break;
|
||||
}
|
||||
INCREF(x);
|
||||
PUSH(x);
|
||||
break;
|
||||
|
@ -1000,6 +1032,11 @@ eval_code(co, globals, locals, arg)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (is_accessobject(x)) {
|
||||
x = getaccessvalue(x, (object *)NULL);
|
||||
if (x == NULL)
|
||||
break;
|
||||
}
|
||||
INCREF(x);
|
||||
PUSH(x);
|
||||
break;
|
||||
|
@ -1011,6 +1048,11 @@ eval_code(co, globals, locals, arg)
|
|||
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 @@ eval_code(co, globals, locals, arg)
|
|||
"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 @@ eval_code(co, globals, locals, arg)
|
|||
"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 @@ eval_code(co, globals, locals, arg)
|
|||
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 @@ fast_2_locals(f)
|
|||
/* 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 @@ fast_2_locals(f)
|
|||
!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 @@ locals_2_fast(f, clear)
|
|||
/* 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 @@ locals_2_fast(f, clear)
|
|||
!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 @@ call_builtin(func, arg)
|
|||
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 @@ import_from(locals, v, name)
|
|||
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 @@ import_from(locals, v, name)
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
137
Python/compile.c
137
Python/compile.c
|
@ -1408,6 +1408,65 @@ com_global_stmt(c, n)
|
|||
}
|
||||
}
|
||||
|
||||
#define strequ(a, b) (strcmp((a), (b)) == 0)
|
||||
|
||||
static void
|
||||
com_access_stmt(c, n)
|
||||
struct compiling *c;
|
||||
node *n;
|
||||
{
|
||||
int i, j, k, mode, imode;
|
||||
object *vmode;
|
||||
REQ(n, access_stmt);
|
||||
/* 'access' NAME (',' NAME)* ':' accesstype (',' accesstype)*
|
||||
accesstype: NAME+ */
|
||||
|
||||
/* Find where the colon is */
|
||||
i = 1;
|
||||
while (TYPE(CHILD(n,i-1)) != COLON)
|
||||
i += 1;
|
||||
|
||||
/* Calculate the mode mask */
|
||||
mode = 0;
|
||||
for (j = i; j < NCH(n); j += 2) {
|
||||
int r=0,w=0,p=0;
|
||||
for (k=0; k<NCH(CHILD(n,j)); k++) {
|
||||
if (strequ(STR(CHILD(CHILD(n,j),k)), "public"))
|
||||
p = 0;
|
||||
else if (strequ(STR(CHILD(CHILD(n,j),k)), "protected"))
|
||||
p = 1;
|
||||
else if (strequ(STR(CHILD(CHILD(n,j),k)), "private"))
|
||||
p = 2;
|
||||
else if (strequ(STR(CHILD(CHILD(n,j),k)), "read"))
|
||||
r = 1;
|
||||
else if (strequ(STR(CHILD(CHILD(n,j),k)), "write"))
|
||||
w = 1;
|
||||
else /* XXX should make this an exception */
|
||||
fprintf(stderr, "bad access type %s\n",
|
||||
STR(CHILD(CHILD(n,j),k)));
|
||||
}
|
||||
if (r == 0 && w == 0)
|
||||
r =w = 1;
|
||||
if (p == 0) {
|
||||
if (r == 1) mode |= AC_R_PUBLIC;
|
||||
if (w == 1) mode |= AC_W_PUBLIC;
|
||||
} else if (p == 1) {
|
||||
if (r == 1) mode |= AC_R_PROTECTED;
|
||||
if (w == 1) mode |= AC_W_PROTECTED;
|
||||
} else {
|
||||
if (r == 1) mode |= AC_R_PRIVATE;
|
||||
if (w == 1) mode |= AC_W_PRIVATE;
|
||||
}
|
||||
}
|
||||
vmode = newintobject((long)mode);
|
||||
imode = com_addconst(c, vmode);
|
||||
XDECREF(vmode);
|
||||
for (i = 1; TYPE(CHILD(n,i-1)) != COLON; i+=2) {
|
||||
com_addoparg(c, LOAD_CONST, imode);
|
||||
com_addopname(c, ACCESS_MODE, CHILD(n, i));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
com_if_stmt(c, n)
|
||||
struct compiling *c;
|
||||
|
@ -1726,23 +1785,7 @@ com_funcdef(c, n)
|
|||
}
|
||||
|
||||
static void
|
||||
com_oldbases(c, n)
|
||||
struct compiling *c;
|
||||
node *n;
|
||||
{
|
||||
int i;
|
||||
REQ(n, baselist);
|
||||
/*
|
||||
baselist: atom arguments (',' atom arguments)*
|
||||
arguments: '(' ')'
|
||||
*/
|
||||
for (i = 0; i < NCH(n); i += 3)
|
||||
com_node(c, CHILD(n, i));
|
||||
com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3);
|
||||
}
|
||||
|
||||
static void
|
||||
com_newbases(c, n)
|
||||
com_bases(c, n)
|
||||
struct compiling *c;
|
||||
node *n;
|
||||
{
|
||||
|
@ -1759,46 +1802,28 @@ com_classdef(c, n)
|
|||
struct compiling *c;
|
||||
node *n;
|
||||
{
|
||||
int i;
|
||||
object *v;
|
||||
REQ(n, classdef);
|
||||
/*
|
||||
classdef: 'class' NAME
|
||||
['(' testlist ')' |'(' ')' ['=' baselist]] ':' suite
|
||||
baselist: atom arguments (',' atom arguments)*
|
||||
arguments: '(' ')'
|
||||
*/
|
||||
/* This piece of code must push a tuple on the stack (the bases) */
|
||||
if (TYPE(CHILD(n, 2)) != LPAR) {
|
||||
/* New syntax without base classes:
|
||||
class NAME ':' suite
|
||||
___________^
|
||||
*/
|
||||
/* classdef: class NAME ['(' testlist ')'] ':' suite */
|
||||
if ((v = newstringobject(STR(CHILD(n, 1)))) == NULL) {
|
||||
c->c_errors++;
|
||||
return;
|
||||
}
|
||||
/* Push the class name on the stack */
|
||||
i = com_addconst(c, v);
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
DECREF(v);
|
||||
/* Push the tuple of base classes on the stack */
|
||||
if (TYPE(CHILD(n, 2)) != LPAR)
|
||||
com_addoparg(c, BUILD_TUPLE, 0);
|
||||
}
|
||||
else {
|
||||
if (TYPE(CHILD(n, 3)) == RPAR) {
|
||||
/* Old syntax with or without base classes:
|
||||
class NAME '(' ')' ['=' baselist] ':' suite
|
||||
_______________^....^...^
|
||||
*/
|
||||
if (TYPE(CHILD(n, 4)) == EQUAL)
|
||||
com_oldbases(c, CHILD(n, 5));
|
||||
else
|
||||
com_addoparg(c, BUILD_TUPLE, 0);
|
||||
}
|
||||
else {
|
||||
/* New syntax with base classes:
|
||||
class NAME '(' testlist ')' ':' suite
|
||||
_______________^
|
||||
*/
|
||||
com_newbases(c, CHILD(n, 3));
|
||||
}
|
||||
}
|
||||
else
|
||||
com_bases(c, CHILD(n, 3));
|
||||
v = (object *)compile(n, c->c_filename);
|
||||
if (v == NULL)
|
||||
c->c_errors++;
|
||||
else {
|
||||
int i = com_addconst(c, v);
|
||||
i = com_addconst(c, v);
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_addbyte(c, BUILD_FUNCTION);
|
||||
com_addbyte(c, UNARY_CALL);
|
||||
|
@ -1882,6 +1907,9 @@ com_node(c, n)
|
|||
case global_stmt:
|
||||
com_global_stmt(c, n);
|
||||
break;
|
||||
case access_stmt:
|
||||
com_access_stmt(c, n);
|
||||
break;
|
||||
case if_stmt:
|
||||
com_if_stmt(c, n);
|
||||
break;
|
||||
|
@ -2084,9 +2112,8 @@ compile_node(c, n)
|
|||
break;
|
||||
|
||||
case classdef: /* A class definition */
|
||||
/* classdef: 'class' NAME
|
||||
['(' testlist ')' |'(' ')' ['=' baselist]]
|
||||
':' suite */
|
||||
/* classdef: 'class' NAME ['(' testlist ')'] ':' suite */
|
||||
c->c_name = STR(CHILD(n, 1));
|
||||
com_node(c, CHILD(n, NCH(n)-1)); /* The suite */
|
||||
com_addbyte(c, LOAD_LOCALS);
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
|
@ -2114,8 +2141,8 @@ compile_node(c, n)
|
|||
|
||||
There is one problem: 'from foo import *' introduces local variables
|
||||
that we can't know while compiling. If this is the case, wo don't
|
||||
optimize at all (this rarely happens, since import is mostly used
|
||||
at the module level).
|
||||
optimize at all (this rarely happens, since this form of import
|
||||
statement is mostly used at the module level).
|
||||
|
||||
Note that, because of this optimization, code like the following
|
||||
won't work:
|
||||
|
|
1026
Python/graminit.c
1026
Python/graminit.c
File diff suppressed because it is too large
Load diff
|
@ -54,7 +54,7 @@ extern char *argv0;
|
|||
|
||||
/* Magic word to reject .pyc files generated by other Python versions */
|
||||
|
||||
#define MAGIC 0x99BE3AL
|
||||
#define MAGIC 0x999901L /* Increment by one for each incompatible change */
|
||||
|
||||
static object *modules;
|
||||
|
||||
|
@ -353,46 +353,27 @@ reload_module(m)
|
|||
return get_module(m, getmodulename(m), (object **)NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
cleardict(d)
|
||||
object *d;
|
||||
{
|
||||
int i;
|
||||
for (i = getdictsize(d); --i >= 0; ) {
|
||||
char *k;
|
||||
k = getdictkey(d, i);
|
||||
if (k != NULL)
|
||||
(void) dictremove(d, k);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
doneimport()
|
||||
{
|
||||
if (modules != NULL) {
|
||||
int i;
|
||||
int pos;
|
||||
object *modname, *module;
|
||||
/* Explicitly erase all modules; this is the safest way
|
||||
to get rid of at least *some* circular dependencies */
|
||||
for (i = getdictsize(modules); --i >= 0; ) {
|
||||
object *k;
|
||||
k = getdict2key(modules, i);
|
||||
if (k != NULL) {
|
||||
object *m;
|
||||
m = dict2lookup(modules, k);
|
||||
if (m == NULL)
|
||||
err_clear();
|
||||
else if (is_moduleobject(m)) {
|
||||
object *d;
|
||||
d = getmoduledict(m);
|
||||
if (d != NULL && is_dictobject(d)) {
|
||||
cleardict(d);
|
||||
}
|
||||
}
|
||||
pos = 0;
|
||||
while (mappinggetnext(modules, &pos, &modname, &module)) {
|
||||
if (is_moduleobject(module)) {
|
||||
object *dict;
|
||||
dict = getmoduledict(module);
|
||||
if (dict != NULL && is_dictobject(dict))
|
||||
mappingclear(dict);
|
||||
}
|
||||
}
|
||||
cleardict(modules);
|
||||
mappingclear(modules);
|
||||
}
|
||||
DECREF(modules);
|
||||
modules = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -174,17 +174,14 @@ w_object(v, p)
|
|||
}
|
||||
}
|
||||
else if (is_dictobject(v)) {
|
||||
int pos;
|
||||
object *key, *value;
|
||||
w_byte(TYPE_DICT, p);
|
||||
/* This one is NULL object terminated! */
|
||||
n = getdictsize(v);
|
||||
for (i = 0; i < n; i++) {
|
||||
object *key, *val;
|
||||
key = getdict2key(v, (int)i);
|
||||
if (key != NULL) {
|
||||
val = dict2lookup(v, key); /* Can't be NULL */
|
||||
w_object(key, p);
|
||||
w_object(val, p);
|
||||
}
|
||||
pos = 0;
|
||||
while (mappinggetnext(v, &pos, &key, &value)) {
|
||||
w_object(key, p);
|
||||
w_object(value, p);
|
||||
}
|
||||
w_object((object *)NULL, p);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue