diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-01-25 20:06:59 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-01-25 20:06:59 (GMT) |
commit | 64949cb753f206c0ca1d83f55d07afd3c179b81a (patch) | |
tree | 5103ffeba20d4a8cd0eefdc177b0e2a91518e0ab /Python/ceval.c | |
parent | fbd849f201a4a8c17745a72eb9f0ee3bae34d330 (diff) | |
download | cpython-64949cb753f206c0ca1d83f55d07afd3c179b81a.zip cpython-64949cb753f206c0ca1d83f55d07afd3c179b81a.tar.gz cpython-64949cb753f206c0ca1d83f55d07afd3c179b81a.tar.bz2 |
PEP 227 implementation
The majority of the changes are in the compiler. The mainloop changes
primarily to implement the new opcodes and to pass a function's
closure to eval_code2(). Frames and functions got new slots to hold
the closure.
Include/compile.h
Add co_freevars and co_cellvars slots to code objects.
Update PyCode_New() to take freevars and cellvars as arguments
Include/funcobject.h
Add func_closure slot to function objects.
Add GetClosure()/SetClosure() functions (and corresponding
macros) for getting at the closure.
Include/frameobject.h
PyFrame_New() now takes a closure.
Include/opcode.h
Add four new opcodes: MAKE_CLOSURE, LOAD_CLOSURE, LOAD_DEREF,
STORE_DEREF.
Remove comment about old requirement for opcodes to fit in 7
bits.
compile.c
Implement changes to code objects for co_freevars and co_cellvars.
Modify symbol table to use st_cur_name (string object for the name
of the current scope) and st_cur_children (list of nested blocks).
Also define st_nested, which might more properly be called
st_cur_nested. Add several DEF_XXX flags to track def-use
information for free variables.
New or modified functions of note:
com_make_closure(struct compiling *, PyCodeObject *)
Emit LOAD_CLOSURE opcodes as needed to pass cells for free
variables into nested scope.
com_addop_varname(struct compiling *, int, char *)
Emits opcodes for LOAD_DEREF and STORE_DEREF.
get_ref_type(struct compiling *, char *name)
Return NAME_CLOSURE if ref type is FREE or CELL
symtable_load_symbols(struct compiling *)
Decides what variables are cell or free based on def-use info.
Can now raise SyntaxError if nested scopes are mixed with
exec or from blah import *.
make_scope_info(PyObject *, PyObject *, int, int)
Helper functions for symtable scope stack.
symtable_update_free_vars(struct symtable *)
After a code block has been analyzed, it must check each of
its children for free variables that are not defined in the
block. If a variable is free in a child and not defined in
the parent, then it is defined by block the enclosing the
current one or it is a global. This does the right logic.
symtable_add_use() is now a macro for symtable_add_def()
symtable_assign(struct symtable *, node *)
Use goto instead of for (;;)
Fixed bug in symtable where name of keyword argument in function
call was treated as assignment in the scope of the call site. Ex:
def f():
g(a=2) # a was considered a local of f
ceval.c
eval_code2() now take one more argument, a closure.
Implement LOAD_CLOSURE, LOAD_DEREF, STORE_DEREF, MAKE_CLOSURE>
Also: When name error occurs for global variable, report that the
name was global in the error mesage.
Objects/frameobject.c
Initialize f_closure to be a tuple containing space for cellvars
and freevars. f_closure is NULL if neither are present.
Objects/funcobject.c
Add support for func_closure.
Python/import.c
Change the magic number.
Python/marshal.c
Track changes to code objects.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 89 |
1 files changed, 77 insertions, 12 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 199272c..c7b5696 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -33,13 +33,16 @@ typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *); +#define REPR(ob) PyString_AS_STRING(PyObject_Repr(ob)) + /* Forward declarations */ static PyObject *eval_code2(PyCodeObject *, PyObject *, PyObject *, PyObject **, int, PyObject **, int, - PyObject **, int); + PyObject **, int, + PyObject *); static PyObject *call_object(PyObject *, PyObject *, PyObject *); static PyObject *call_cfunction(PyObject *, PyObject *, PyObject *); @@ -78,6 +81,8 @@ static void format_exc_check_arg(PyObject *, char *, PyObject *); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" +#define GLOBAL_NAME_ERROR_MSG \ + "global name '%.200s' is not defined" #define UNBOUNDLOCAL_ERROR_MSG \ "local variable '%.200s' referenced before assignment" @@ -335,7 +340,8 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) globals, locals, (PyObject **)NULL, 0, (PyObject **)NULL, 0, - (PyObject **)NULL, 0); + (PyObject **)NULL, 0, + NULL); } @@ -344,7 +350,7 @@ PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) static PyObject * eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, PyObject **args, int argcount, PyObject **kws, int kwcount, - PyObject **defs, int defcount) + PyObject **defs, int defcount, PyObject *closure) { #ifdef DXPAIRS int lastopcode = 0; @@ -425,11 +431,9 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, lltrace = PyDict_GetItemString(globals, "__lltrace__") != NULL; #endif - f = PyFrame_New( - tstate, /*back*/ + f = PyFrame_New(tstate, /*back*/ co, /*code*/ - globals, /*globals*/ - locals); /*locals*/ + globals, locals, closure); if (f == NULL) return NULL; @@ -1535,7 +1539,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, w = GETNAMEV(oparg); if ((err = PyDict_DelItem(f->f_globals, w)) != 0) format_exc_check_arg( - PyExc_NameError, NAME_ERROR_MSG ,w); + PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w); break; case LOAD_CONST: @@ -1577,7 +1581,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, if (x == NULL) { format_exc_check_arg( PyExc_NameError, - NAME_ERROR_MSG ,w); + GLOBAL_NAME_ERROR_MSG ,w); break; } } @@ -1618,6 +1622,25 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, SETLOCAL(oparg, NULL); continue; + case LOAD_CLOSURE: + x = PyTuple_GET_ITEM(f->f_closure, oparg); + Py_INCREF(x); + PUSH(x); + break; + + case LOAD_DEREF: + x = PyTuple_GET_ITEM(f->f_closure, oparg); + w = PyCell_Get(x); + Py_INCREF(w); + PUSH(w); + break; + + case STORE_DEREF: + w = POP(); + x = PyTuple_GET_ITEM(f->f_closure, oparg); + PyCell_Set(x, w); + continue; + case BUILD_TUPLE: x = PyTuple_New(oparg); if (x != NULL) { @@ -1939,6 +1962,46 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, PUSH(x); break; + case MAKE_CLOSURE: + { + int nfree; + v = POP(); /* code object */ + x = PyFunction_New(v, f->f_globals); + nfree = PyTuple_GET_SIZE(((PyCodeObject *)v)->co_freevars); + Py_DECREF(v); + /* XXX Maybe this should be a separate opcode? */ + if (x != NULL && nfree > 0) { + v = PyTuple_New(nfree); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + while (--nfree >= 0) { + w = POP(); + PyTuple_SET_ITEM(v, nfree, w); + } + err = PyFunction_SetClosure(x, v); + Py_DECREF(v); + } + if (x != NULL && oparg > 0) { + v = PyTuple_New(oparg); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + while (--oparg >= 0) { + w = POP(); + PyTuple_SET_ITEM(v, oparg, w); + } + err = PyFunction_SetDefaults(x, v); + Py_DECREF(v); + } + PUSH(x); + break; + } + case BUILD_SLICE: if (oparg == 3) w = POP(); @@ -2761,8 +2824,8 @@ call_eval_code2(PyObject *func, PyObject *arg, PyObject *kw) (PyCodeObject *)PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), (PyObject *)NULL, &PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg), - k, nk, - d, nd); + k, nk, d, nd, + PyFunction_GET_CLOSURE(func)); if (k != NULL) PyMem_DEL(k); @@ -2805,6 +2868,7 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) PyObject *co = PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure = PyFunction_GET_CLOSURE(func); PyObject **d = NULL; int nd = 0; @@ -2814,7 +2878,8 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) } return eval_code2((PyCodeObject *)co, globals, (PyObject *)NULL, (*pp_stack)-n, na, - (*pp_stack)-2*nk, nk, d, nd); + (*pp_stack)-2*nk, nk, d, nd, + closure); } static PyObject * |