mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
Patch #1550800: make exec a function.
This commit is contained in:
parent
4e472e05bd
commit
7cae87ca7b
105 changed files with 1246 additions and 1583 deletions
|
@ -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;
|
||||
|
|
36
Python/ast.c
36
Python/ast.c
|
@ -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:
|
||||
|
|
|
@ -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},
|
||||
|
|
117
Python/ceval.c
117
Python/ceval.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
1609
Python/graminit.c
1609
Python/graminit.c
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue