Patch #1550800: make exec a function.

This commit is contained in:
Georg Brandl 2006-09-06 06:51:57 +00:00
parent 4e472e05bd
commit 7cae87ca7b
105 changed files with 1246 additions and 1583 deletions

View file

@ -123,12 +123,6 @@ static char *ImportFrom_fields[]={
"names",
"level",
};
static PyTypeObject *Exec_type;
static char *Exec_fields[]={
"body",
"globals",
"locals",
};
static PyTypeObject *Global_type;
static char *Global_fields[]={
"names",
@ -494,8 +488,6 @@ static int init_types(void)
ImportFrom_type = make_type("ImportFrom", stmt_type, ImportFrom_fields,
3);
if (!ImportFrom_type) return 0;
Exec_type = make_type("Exec", stmt_type, Exec_fields, 3);
if (!Exec_type) return 0;
Global_type = make_type("Global", stmt_type, Global_fields, 1);
if (!Global_type) return 0;
Expr_type = make_type("Expr", stmt_type, Expr_fields, 1);
@ -1169,30 +1161,6 @@ ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int
return p;
}
stmt_ty
Exec(expr_ty body, expr_ty globals, expr_ty locals, int lineno, int col_offset,
PyArena *arena)
{
stmt_ty p;
if (!body) {
PyErr_SetString(PyExc_ValueError,
"field body is required for Exec");
return NULL;
}
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p) {
PyErr_NoMemory();
return NULL;
}
p->kind = Exec_kind;
p->v.Exec.body = body;
p->v.Exec.globals = globals;
p->v.Exec.locals = locals;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
stmt_ty
Global(asdl_seq * names, int lineno, int col_offset, PyArena *arena)
{
@ -2274,25 +2242,6 @@ ast2obj_stmt(void* _o)
goto failed;
Py_DECREF(value);
break;
case Exec_kind:
result = PyType_GenericNew(Exec_type, NULL, NULL);
if (!result) goto failed;
value = ast2obj_expr(o->v.Exec.body);
if (!value) goto failed;
if (PyObject_SetAttrString(result, "body", value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_expr(o->v.Exec.globals);
if (!value) goto failed;
if (PyObject_SetAttrString(result, "globals", value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_expr(o->v.Exec.locals);
if (!value) goto failed;
if (PyObject_SetAttrString(result, "locals", value) == -1)
goto failed;
Py_DECREF(value);
break;
case Global_kind:
result = PyType_GenericNew(Global_type, NULL, NULL);
if (!result) goto failed;
@ -3082,7 +3031,6 @@ init_ast(void)
return;
if (PyDict_SetItemString(d, "ImportFrom", (PyObject*)ImportFrom_type) <
0) return;
if (PyDict_SetItemString(d, "Exec", (PyObject*)Exec_type) < 0) return;
if (PyDict_SetItemString(d, "Global", (PyObject*)Global_type) < 0)
return;
if (PyDict_SetItemString(d, "Expr", (PyObject*)Expr_type) < 0) return;

View file

@ -2399,37 +2399,6 @@ ast_for_global_stmt(struct compiling *c, const node *n)
return Global(s, LINENO(n), n->n_col_offset, c->c_arena);
}
static stmt_ty
ast_for_exec_stmt(struct compiling *c, const node *n)
{
expr_ty expr1, globals = NULL, locals = NULL;
int n_children = NCH(n);
if (n_children != 2 && n_children != 4 && n_children != 6) {
PyErr_Format(PyExc_SystemError,
"poorly formed 'exec' statement: %d parts to statement",
n_children);
return NULL;
}
/* exec_stmt: 'exec' expr ['in' test [',' test]] */
REQ(n, exec_stmt);
expr1 = ast_for_expr(c, CHILD(n, 1));
if (!expr1)
return NULL;
if (n_children >= 4) {
globals = ast_for_expr(c, CHILD(n, 3));
if (!globals)
return NULL;
}
if (n_children == 6) {
locals = ast_for_expr(c, CHILD(n, 5));
if (!locals)
return NULL;
}
return Exec(expr1, globals, locals, LINENO(n), n->n_col_offset, c->c_arena);
}
static stmt_ty
ast_for_assert_stmt(struct compiling *c, const node *n)
{
@ -2944,8 +2913,7 @@ ast_for_stmt(struct compiling *c, const node *n)
REQ(n, small_stmt);
n = CHILD(n, 0);
/* small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt
| flow_stmt | import_stmt | global_stmt | exec_stmt
| assert_stmt
| flow_stmt | import_stmt | global_stmt | assert_stmt
*/
switch (TYPE(n)) {
case expr_stmt:
@ -2962,8 +2930,6 @@ ast_for_stmt(struct compiling *c, const node *n)
return ast_for_import_stmt(c, n);
case global_stmt:
return ast_for_global_stmt(c, n);
case exec_stmt:
return ast_for_exec_stmt(c, n);
case assert_stmt:
return ast_for_assert_stmt(c, n);
default:

View file

@ -403,7 +403,7 @@ PyDoc_STRVAR(compile_doc,
"compile(source, filename, mode[, flags[, dont_inherit]]) -> code object\n\
\n\
Compile the source string (a Python module, statement or expression)\n\
into a code object that can be executed by the exec statement or eval().\n\
into a code object that can be executed by exec() or eval().\n\
The filename will be used for run-time error messages.\n\
The mode must be 'exec' to compile a module, 'single' to compile a\n\
single (interactive) statement, or 'eval' to compile an expression.\n\
@ -543,6 +543,114 @@ The globals must be a dictionary and locals can be any mappping,\n\
defaulting to the current globals and locals.\n\
If only globals is given, locals defaults to it.\n");
static PyObject *
builtin_exec(PyObject *self, PyObject *args)
{
PyObject *v;
PyObject *prog, *globals = Py_None, *locals = Py_None;
int plain = 0;
if (!PyArg_ParseTuple(args, "O|OO:exec", &prog, &globals, &locals))
return NULL;
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {
locals = PyEval_GetLocals();
plain = 1;
}
if (!globals || !locals) {
PyErr_SetString(PyExc_SystemError,
"globals and locals cannot be NULL");
return NULL;
}
}
else if (locals == Py_None)
locals = globals;
if (!PyString_Check(prog) &&
!PyUnicode_Check(prog) &&
!PyCode_Check(prog) &&
!PyFile_Check(prog)) {
PyErr_Format(PyExc_TypeError,
"exec() arg 1 must be a string, file, or code "
"object, not %.100s", prog->ob_type->tp_name);
return NULL;
}
if (!PyDict_Check(globals)) {
PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.100s",
globals->ob_type->tp_name);
return NULL;
}
if (!PyMapping_Check(locals)) {
PyErr_Format(PyExc_TypeError,
"arg 3 must be a mapping or None, not %.100s",
locals->ob_type->tp_name);
return NULL;
}
if (PyDict_GetItemString(globals, "__builtins__") == NULL) {
if (PyDict_SetItemString(globals, "__builtins__",
PyEval_GetBuiltins()) != 0)
return NULL;
}
if (PyCode_Check(prog)) {
if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) {
PyErr_SetString(PyExc_TypeError,
"code object passed to exec() may not "
"contain free variables");
return NULL;
}
v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
}
else if (PyFile_Check(prog)) {
FILE *fp = PyFile_AsFile(prog);
char *name = PyString_AsString(PyFile_Name(prog));
PyCompilerFlags cf;
cf.cf_flags = 0;
if (PyEval_MergeCompilerFlags(&cf))
v = PyRun_FileFlags(fp, name, Py_file_input, globals,
locals, &cf);
else
v = PyRun_File(fp, name, Py_file_input, globals,
locals);
}
else {
PyObject *tmp = NULL;
char *str;
PyCompilerFlags cf;
cf.cf_flags = 0;
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(prog)) {
tmp = PyUnicode_AsUTF8String(prog);
if (tmp == NULL)
return NULL;
prog = tmp;
cf.cf_flags |= PyCF_SOURCE_IS_UTF8;
}
#endif
if (PyString_AsStringAndSize(prog, &str, NULL))
return NULL;
if (PyEval_MergeCompilerFlags(&cf))
v = PyRun_StringFlags(str, Py_file_input, globals,
locals, &cf);
else
v = PyRun_String(str, Py_file_input, globals, locals);
Py_XDECREF(tmp);
}
if (v == NULL)
return NULL;
Py_DECREF(v);
Py_RETURN_NONE;
}
PyDoc_STRVAR(exec_doc,
"exec(object[, globals[, locals]])\n\
\n\
Read and execute code from a object, which can be a string, a code\n\
object or a file object.\n\
The globals and locals are dictionaries, defaulting to the current\n\
globals and locals. If only globals is given, locals defaults to it.");
static PyObject *
builtin_execfile(PyObject *self, PyObject *args)
@ -1884,6 +1992,7 @@ static PyMethodDef builtin_methods[] = {
{"dir", builtin_dir, METH_VARARGS, dir_doc},
{"divmod", builtin_divmod, METH_VARARGS, divmod_doc},
{"eval", builtin_eval, METH_VARARGS, eval_doc},
{"exec", builtin_exec, METH_VARARGS, exec_doc},
{"execfile", builtin_execfile, METH_VARARGS, execfile_doc},
{"filter", builtin_filter, METH_VARARGS, filter_doc},
{"getattr", builtin_getattr, METH_VARARGS, getattr_doc},

View file

@ -118,8 +118,6 @@ static PyObject * cmp_outcome(int, PyObject *, PyObject *);
static PyObject * import_from(PyObject *, PyObject *);
static int import_all_from(PyObject *, PyObject *);
static PyObject * build_class(PyObject *, PyObject *, PyObject *);
static int exec_statement(PyFrameObject *,
PyObject *, PyObject *, PyObject *);
static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *);
static void reset_exc_info(PyThreadState *);
static void format_exc_check_arg(PyObject *, char *, PyObject *);
@ -580,7 +578,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
It's a case-by-case judgement. I'll use intr1 for the following
cases:
EXEC_STMT
IMPORT_STAR
IMPORT_FROM
CALL_FUNCTION (and friends)
@ -1622,19 +1619,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
why = WHY_YIELD;
goto fast_yield;
case EXEC_STMT:
w = TOP();
v = SECOND();
u = THIRD();
STACKADJ(-3);
READ_TIMESTAMP(intr0);
err = exec_statement(f, u, v, w);
READ_TIMESTAMP(intr1);
Py_DECREF(u);
Py_DECREF(v);
Py_DECREF(w);
break;
case POP_BLOCK:
{
PyTryBlock *b = PyFrame_BlockPop(f);
@ -4072,107 +4056,6 @@ build_class(PyObject *methods, PyObject *bases, PyObject *name)
return result;
}
static int
exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
PyObject *locals)
{
int n;
PyObject *v;
int plain = 0;
if (PyTuple_Check(prog) && globals == Py_None && locals == Py_None &&
((n = PyTuple_Size(prog)) == 2 || n == 3)) {
/* Backward compatibility hack */
globals = PyTuple_GetItem(prog, 1);
if (n == 3)
locals = PyTuple_GetItem(prog, 2);
prog = PyTuple_GetItem(prog, 0);
}
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None) {
locals = PyEval_GetLocals();
plain = 1;
}
if (!globals || !locals) {
PyErr_SetString(PyExc_SystemError,
"globals and locals cannot be NULL");
return -1;
}
}
else if (locals == Py_None)
locals = globals;
if (!PyString_Check(prog) &&
!PyUnicode_Check(prog) &&
!PyCode_Check(prog) &&
!PyFile_Check(prog)) {
PyErr_SetString(PyExc_TypeError,
"exec: arg 1 must be a string, file, or code object");
return -1;
}
if (!PyDict_Check(globals)) {
PyErr_SetString(PyExc_TypeError,
"exec: arg 2 must be a dictionary or None");
return -1;
}
if (!PyMapping_Check(locals)) {
PyErr_SetString(PyExc_TypeError,
"exec: arg 3 must be a mapping or None");
return -1;
}
if (PyDict_GetItemString(globals, "__builtins__") == NULL)
PyDict_SetItemString(globals, "__builtins__", f->f_builtins);
if (PyCode_Check(prog)) {
if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) {
PyErr_SetString(PyExc_TypeError,
"code object passed to exec may not contain free variables");
return -1;
}
v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
}
else if (PyFile_Check(prog)) {
FILE *fp = PyFile_AsFile(prog);
char *name = PyString_AsString(PyFile_Name(prog));
PyCompilerFlags cf;
cf.cf_flags = 0;
if (PyEval_MergeCompilerFlags(&cf))
v = PyRun_FileFlags(fp, name, Py_file_input, globals,
locals, &cf);
else
v = PyRun_File(fp, name, Py_file_input, globals,
locals);
}
else {
PyObject *tmp = NULL;
char *str;
PyCompilerFlags cf;
cf.cf_flags = 0;
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(prog)) {
tmp = PyUnicode_AsUTF8String(prog);
if (tmp == NULL)
return -1;
prog = tmp;
cf.cf_flags |= PyCF_SOURCE_IS_UTF8;
}
#endif
if (PyString_AsStringAndSize(prog, &str, NULL))
return -1;
if (PyEval_MergeCompilerFlags(&cf))
v = PyRun_StringFlags(str, Py_file_input, globals,
locals, &cf);
else
v = PyRun_String(str, Py_file_input, globals, locals);
Py_XDECREF(tmp);
}
if (plain)
PyFrame_LocalsToFast(f, 0);
if (v == NULL)
return -1;
Py_DECREF(v);
return 0;
}
static void
format_exc_check_arg(PyObject *exc, char *format_str, PyObject *obj)
{

View file

@ -814,8 +814,6 @@ opcode_stack_effect(int opcode, int oparg)
return -1;
case IMPORT_STAR:
return -1;
case EXEC_STMT:
return -3;
case YIELD_VALUE:
return 0;
@ -2112,21 +2110,6 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
return compiler_import(c, s);
case ImportFrom_kind:
return compiler_from_import(c, s);
case Exec_kind:
VISIT(c, expr, s->v.Exec.body);
if (s->v.Exec.globals) {
VISIT(c, expr, s->v.Exec.globals);
if (s->v.Exec.locals) {
VISIT(c, expr, s->v.Exec.locals);
} else {
ADDOP(c, DUP_TOP);
}
} else {
ADDOP_O(c, LOAD_CONST, Py_None, consts);
ADDOP(c, DUP_TOP);
}
ADDOP(c, EXEC_STMT);
break;
case Global_kind:
break;
case Expr_kind:

File diff suppressed because it is too large Load diff

View file

@ -480,8 +480,7 @@ check_unoptimized(const PySTEntryObject* ste) {
"is a nested function");
switch (ste->ste_unoptimized) {
case OPT_TOPLEVEL: /* exec / import * at top-level is fine */
case OPT_EXEC: /* qualified exec is fine */
case OPT_TOPLEVEL: /* import * at top-level is fine */
return 1;
case OPT_IMPORT_STAR:
PyOS_snprintf(buf, sizeof(buf),
@ -489,18 +488,6 @@ check_unoptimized(const PySTEntryObject* ste) {
"because it is %s",
PyString_AS_STRING(ste->ste_name), trailer);
break;
case OPT_BARE_EXEC:
PyOS_snprintf(buf, sizeof(buf),
"unqualified exec is not allowed in function "
"'%.100s' it %s",
PyString_AS_STRING(ste->ste_name), trailer);
break;
default:
PyOS_snprintf(buf, sizeof(buf),
"function '%.100s' uses import * and bare exec, "
"which are illegal because it %s",
PyString_AS_STRING(ste->ste_name), trailer);
break;
}
PyErr_SetString(PyExc_SyntaxError, buf);
@ -1045,19 +1032,6 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno)
st->st_cur->ste_opt_lineno = s->lineno;
break;
case Exec_kind:
VISIT(st, expr, s->v.Exec.body);
if (!st->st_cur->ste_opt_lineno)
st->st_cur->ste_opt_lineno = s->lineno;
if (s->v.Exec.globals) {
st->st_cur->ste_unoptimized |= OPT_EXEC;
VISIT(st, expr, s->v.Exec.globals);
if (s->v.Exec.locals)
VISIT(st, expr, s->v.Exec.locals);
} else {
st->st_cur->ste_unoptimized |= OPT_BARE_EXEC;
}
break;
case Global_kind: {
int i;
asdl_seq *seq = s->v.Global.names;