[Python-checkins] python/dist/src/Python newcompile.c, 1.1.2.64,
1.1.2.65
nnorwitz at projects.sourceforge.net
nnorwitz at projects.sourceforge.net
Tue Jan 27 14:05:46 EST 2004
Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26950/Python
Modified Files:
Tag: ast-branch
newcompile.c
Log Message:
Start implementing closures
Index: newcompile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v
retrieving revision 1.1.2.64
retrieving revision 1.1.2.65
diff -C2 -d -r1.1.2.64 -r1.1.2.65
*** newcompile.c 26 Jan 2004 14:38:58 -0000 1.1.2.64
--- newcompile.c 27 Jan 2004 19:05:43 -0000 1.1.2.65
***************
*** 78,81 ****
--- 78,83 ----
PyObject *u_names; /* all names */
PyObject *u_varnames; /* local variables */
+ PyObject *u_cellvars; /* cell variables */
+ PyObject *u_freevars; /* free variables */
int u_argcount; /* number of arguments for block */
***************
*** 275,278 ****
--- 277,311 ----
}
+ static PyObject *
+ dictbytype(PyObject *src, int scope_type)
+ {
+ int pos = 0, i = 0, scope;
+ PyObject *k, *v, *dest = PyDict_New();
+
+ if (dest == NULL)
+ return NULL;
+
+ while (PyDict_Next(src, &pos, &k, &v)) {
+ /* XXX this should probably be a macro in symtable.h */
+ assert(PyInt_Check(v));
+ scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
+
+ if (scope == scope_type) {
+ PyObject *item = PyInt_FromLong(i);
+ if (item == NULL) {
+ Py_DECREF(dest);
+ return NULL;
+ }
+ if (PyDict_SetItem(dest, k, item) < 0) {
+ Py_DECREF(item);
+ Py_DECREF(dest);
+ return NULL;
+ }
+ Py_DECREF(item);
+ }
+ }
+ return dest;
+ }
+
static void
compiler_display_symbols(PyObject *name, PyObject *symbols)
***************
*** 324,328 ****
u->u_name = name;
u->u_varnames = list2dict(u->u_ste->ste_varnames);
! Py_INCREF(u->u_varnames);
u->u_nblocks = 0;
u->u_nalloc = DEFAULT_BLOCKS;
--- 357,362 ----
u->u_name = name;
u->u_varnames = list2dict(u->u_ste->ste_varnames);
! u->u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL);
! u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE);
u->u_nblocks = 0;
u->u_nalloc = DEFAULT_BLOCKS;
***************
*** 334,338 ****
u->u_nfblocks = 0;
u->u_lineno = 0;
! u->u_lineno_set = true;
memset(u->u_blocks, 0, sizeof(struct basicblock *) * DEFAULT_BLOCKS);
u->u_consts = PyDict_New();
--- 368,372 ----
u->u_nfblocks = 0;
u->u_lineno = 0;
! u->u_lineno_set = false;
memset(u->u_blocks, 0, sizeof(struct basicblock *) * DEFAULT_BLOCKS);
u->u_consts = PyDict_New();
***************
*** 393,396 ****
--- 427,432 ----
Py_XDECREF(u->u_names);
Py_XDECREF(u->u_varnames);
+ Py_XDECREF(u->u_freevars);
+ Py_XDECREF(u->u_cellvars);
PyObject_Free(u);
}
***************
*** 732,735 ****
--- 768,852 ----
}
+ /* The test for LOCAL must come before the test for FREE in order to
+ handle classes where name is both local and free. The local var is
+ a method and the free var is a free var referenced within a method.
+ */
+
+ static int
+ get_ref_type(struct compiler *c, PyObject *name)
+ {
+ int scope = PyST_GetScope(c->u->u_ste, name);
+ if (scope == 0) {
+ char buf[350];
+ PyOS_snprintf(buf, sizeof(buf),
+ "unknown scope for %.100s in %.100s(%s) in %s\n"
+ "symbols: %s\nlocals: %s\nglobals: %s\n",
+ PyString_AS_STRING(name),
+ PyString_AS_STRING(c->u->u_name),
+ PyObject_REPR(c->c_st->st_cur->ste_id),
+ c->c_filename,
+ PyObject_REPR(c->c_st->st_cur->ste_symbols),
+ PyObject_REPR(c->u->u_varnames),
+ PyObject_REPR(c->u->u_names)
+ );
+ Py_FatalError(buf);
+ }
+
+ return scope;
+ }
+
+ static int
+ compiler_lookup_arg(PyObject *dict, PyObject *name)
+ {
+ PyObject *v = PyDict_GetItem(dict, name);
+ if (v == NULL)
+ return -1;
+ return PyInt_AS_LONG(v);
+ }
+
+ static int
+ compiler_make_closure(struct compiler *c, PyCodeObject *co, int args)
+ {
+ int i, free = PyCode_GetNumFree(co);
+ if (free == 0) {
+ ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
+ ADDOP_I(c, MAKE_FUNCTION, args);
+ return 1;
+ }
+ for (i = 0; i < free; ++i) {
+ /* Bypass com_addop_varname because it will generate
+ LOAD_DEREF but LOAD_CLOSURE is needed.
+ */
+ PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
+ int arg, reftype;
+
+ /* Special case: If a class contains a method with a
+ free variable that has the same name as a method,
+ the name will be considered free *and* local in the
+ class. It should be handled by the closure, as
+ well as by the normal name loookup logic.
+ */
+ reftype = get_ref_type(c, name);
+ if (reftype == CELL)
+ arg = compiler_lookup_arg(c->u->u_cellvars, name);
+ else /* (reftype == FREE) */
+ arg = compiler_lookup_arg(c->u->u_freevars, name);
+ if (arg == -1) {
+ fprintf(stderr, "lookup %s in %s %d %d\n"
+ "freevars of %s: %s\n",
+ PyObject_REPR(name),
+ PyString_AS_STRING(c->u->u_name),
+ reftype, arg,
+ PyString_AS_STRING(co->co_name),
+ PyObject_REPR(co->co_freevars));
+ Py_FatalError("compiler_make_closure()");
+ }
+ ADDOP_I(c, LOAD_CLOSURE, arg);
+ }
+ ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
+ ADDOP_I(c, MAKE_CLOSURE, args);
+ return 1;
+ }
+
static int
compiler_function(struct compiler *c, stmt_ty s)
***************
*** 769,775 ****
compiler_exit_scope(c);
! /* XXX closure */
! ADDOP_O(c, LOAD_CONST, (PyObject *)co, consts);
! ADDOP_I(c, MAKE_FUNCTION, asdl_seq_LEN(args->defaults));
if (!compiler_nameop(c, s->v.FunctionDef.name, Store))
return 0;
--- 886,890 ----
compiler_exit_scope(c);
! compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));
if (!compiler_nameop(c, s->v.FunctionDef.name, Store))
return 0;
***************
*** 816,822 ****
compiler_exit_scope(c);
! /* XXX closure */
! ADDOP_O(c, LOAD_CONST, (PyObject *)co, consts);
! ADDOP_I(c, MAKE_FUNCTION, 0);
ADDOP_I(c, CALL_FUNCTION, 0);
ADDOP(c, BUILD_CLASS);
--- 931,935 ----
compiler_exit_scope(c);
! compiler_make_closure(c, co, 0);
ADDOP_I(c, CALL_FUNCTION, 0);
ADDOP(c, BUILD_CLASS);
***************
*** 842,846 ****
if (!compiler_enter_scope(c, name, (void *)e))
return 0;
! c->u->u_argcount = asdl_seq_LEN(e->v.Lambda.args->args);
VISIT(c, expr, e->v.Lambda.body);
ADDOP(c, RETURN_VALUE);
--- 955,959 ----
if (!compiler_enter_scope(c, name, (void *)e))
return 0;
! c->u->u_argcount = asdl_seq_LEN(args->args);
VISIT(c, expr, e->v.Lambda.body);
ADDOP(c, RETURN_VALUE);
***************
*** 850,857 ****
compiler_exit_scope(c);
! /* XXX closure */
! ADDOP_O(c, LOAD_CONST, (PyObject *)co, consts);
! ADDOP_I(c, MAKE_FUNCTION, asdl_seq_LEN(args->defaults));
!
Py_DECREF(name);
--- 963,967 ----
compiler_exit_scope(c);
! compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));
Py_DECREF(name);
***************
*** 2522,2526 ****
PyObject *filename = NULL;
PyObject *name = NULL;
! PyObject *nil = PyTuple_New(0);
int nlocals;
--- 2632,2637 ----
PyObject *filename = NULL;
PyObject *name = NULL;
! PyObject *freevars = NULL;
! PyObject *cellvars = NULL;
int nlocals;
***************
*** 2532,2546 ****
goto error;
varnames = PySequence_Tuple(c->u->u_ste->ste_varnames);
! if (!varnames)
! goto error;
filename = PyString_FromString(c->c_filename);
if (!filename)
goto error;
! nlocals = PyList_GET_SIZE(c->u->u_varnames);
co = PyCode_New(c->u->u_argcount, nlocals, stackdepth(c),
compute_code_flags(c),
a->a_bytecode, consts, names, varnames,
! nil, nil,
filename, c->u->u_name,
a->a_firstlineno,
--- 2643,2660 ----
goto error;
varnames = PySequence_Tuple(c->u->u_ste->ste_varnames);
! freevars = PySequence_Tuple(c->u->u_freevars);
! cellvars = PySequence_Tuple(c->u->u_cellvars);
! if (!varnames || !freevars || !cellvars)
! goto error;
!
filename = PyString_FromString(c->c_filename);
if (!filename)
goto error;
! nlocals = PyDict_Size(c->u->u_varnames);
co = PyCode_New(c->u->u_argcount, nlocals, stackdepth(c),
compute_code_flags(c),
a->a_bytecode, consts, names, varnames,
! freevars, cellvars,
filename, c->u->u_name,
a->a_firstlineno,
***************
*** 2552,2557 ****
Py_XDECREF(filename);
Py_XDECREF(name);
return co;
-
}
--- 2666,2672 ----
Py_XDECREF(filename);
Py_XDECREF(name);
+ Py_XDECREF(freevars);
+ Py_XDECREF(cellvars);
return co;
}
More information about the Python-checkins
mailing list