From 9f324e964e06c79f9c47501afa12b1af4cb1a75f Mon Sep 17 00:00:00 2001 From: Jeremy Hylton Date: Thu, 1 Mar 2001 22:59:14 +0000 Subject: Useful future statement support for the interactive interpreter (Also remove warning about module-level global decl, because we can't distinguish from code passed to exec.) Define PyCompilerFlags type contains a single element, cf_nested_scopes, that is true if a nested scopes future statement has been entered at the interactive prompt. New API functions: PyNode_CompileFlags() PyRun_InteractiveOneFlags() -- same as their non Flags counterparts except that the take an optional PyCompilerFlags pointer compile.c: In jcompile() use PyCompilerFlags argument. If cf_nested_scopes is true, compile code with nested scopes. If it is false, but the code has a valid future nested scopes statement, set it to true. pythonrun.c: Create a new PyCompilerFlags object in PyRun_InteractiveLoop() and thread it through to PyRun_InteractiveOneFlags(). --- Include/compile.h | 2 ++ Include/pythonrun.h | 5 +++++ Python/compile.c | 38 +++++++++++++++++++++++++++----------- Python/pythonrun.c | 40 +++++++++++++++++++++++++--------------- 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/Include/compile.h b/Include/compile.h index 45854e9..deb8ee8 100644 --- a/Include/compile.h +++ b/Include/compile.h @@ -57,6 +57,8 @@ typedef struct { } PyFutureFeatures; DL_IMPORT(PyFutureFeatures *) PyNode_Future(struct _node *, char *); +DL_IMPORT(PyCodeObject *) PyNode_CompileFlags(struct _node *, char *, + PyCompilerFlags *); #define NESTED_SCOPES_DEFAULT 0 #define FUTURE_NESTED_SCOPES "nested_scopes" diff --git a/Include/pythonrun.h b/Include/pythonrun.h index 13ed471..3f9f70b 100644 --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -7,6 +7,10 @@ extern "C" { #endif +typedef struct { + int cf_nested_scopes; +} PyCompilerFlags; + DL_IMPORT(void) Py_SetProgramName(char *); DL_IMPORT(char *) Py_GetProgramName(void); @@ -26,6 +30,7 @@ DL_IMPORT(int) PyRun_SimpleString(char *); DL_IMPORT(int) PyRun_SimpleFile(FILE *, char *); DL_IMPORT(int) PyRun_SimpleFileEx(FILE *, char *, int); DL_IMPORT(int) PyRun_InteractiveOne(FILE *, char *); +DL_IMPORT(int) PyRun_InteractiveOneFlags(FILE *, char *, PyCompilerFlags *); DL_IMPORT(int) PyRun_InteractiveLoop(FILE *, char *); DL_IMPORT(struct _node *) PyParser_SimpleParseString(char *, int); diff --git a/Python/compile.c b/Python/compile.c index efef05b..fe4d05e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -471,7 +471,8 @@ static int com_argdefs(struct compiling *, node *); static void com_assign(struct compiling *, node *, int, node *); static void com_assign_name(struct compiling *, node *, int); static PyCodeObject *icompile(node *, struct compiling *); -static PyCodeObject *jcompile(node *, char *, struct compiling *); +static PyCodeObject *jcompile(node *, char *, struct compiling *, + PyCompilerFlags *); static PyObject *parsestrplus(node *); static PyObject *parsestr(char *); static node *get_rawdocstring(node *); @@ -3816,7 +3817,13 @@ dict_keys_inorder(PyObject *dict, int offset) PyCodeObject * PyNode_Compile(node *n, char *filename) { - return jcompile(n, filename, NULL); + return PyNode_CompileFlags(n, filename, NULL); +} + +PyCodeObject * +PyNode_CompileFlags(node *n, char *filename, PyCompilerFlags *flags) +{ + return jcompile(n, filename, NULL, flags); } struct symtable * @@ -3844,11 +3851,12 @@ PyNode_CompileSymtable(node *n, char *filename) static PyCodeObject * icompile(node *n, struct compiling *base) { - return jcompile(n, base->c_filename, base); + return jcompile(n, base->c_filename, base, NULL); } static PyCodeObject * -jcompile(node *n, char *filename, struct compiling *base) +jcompile(node *n, char *filename, struct compiling *base, + PyCompilerFlags *flags) { struct compiling sc; PyCodeObject *co; @@ -3864,7 +3872,17 @@ jcompile(node *n, char *filename, struct compiling *base) } else { sc.c_private = NULL; sc.c_future = PyNode_Future(n, filename); - if (sc.c_future == NULL || symtable_build(&sc, n) < 0) { + if (sc.c_future == NULL) { + com_free(&sc); + return NULL; + } + if (flags) { + if (flags->cf_nested_scopes) + sc.c_future->ff_nested_scopes = 1; + else if (sc.c_future->ff_nested_scopes) + flags->cf_nested_scopes = 1; + } + if (symtable_build(&sc, n) < 0) { com_free(&sc); return NULL; } @@ -4952,12 +4970,10 @@ symtable_global(struct symtable *st, node *n) { int i; - if (st->st_nscopes == 1) { - /* XXX must check that we are compiling file_input */ - if (symtable_warn(st, - "global statement has no meaning at module level") < 0) - return; - } + /* XXX It might be helpful to warn about module-level global + statements, but it's hard to tell the difference between + module-level and a string passed to exec. + */ for (i = 1; i < NCH(n); i += 2) { char *name = STR(CHILD(n, i)); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 7d73395..f7c2820 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -36,12 +36,11 @@ extern grammar _PyParser_Grammar; /* From graminit.c */ /* Forward */ static void initmain(void); static void initsite(void); -static PyObject *run_err_node(node *n, char *filename, - PyObject *globals, PyObject *locals); -static PyObject *run_node(node *n, char *filename, - PyObject *globals, PyObject *locals); -static PyObject *run_pyc_file(FILE *fp, char *filename, - PyObject *globals, PyObject *locals); +static PyObject *run_err_node(node *, char *, PyObject *, PyObject *, + PyCompilerFlags *); +static PyObject *run_node(node *, char *, PyObject *, PyObject *, + PyCompilerFlags *); +static PyObject *run_pyc_file(FILE *, char *, PyObject *, PyObject *); static void err_input(perrdetail *); static void initsigs(void); static void call_sys_exitfunc(void); @@ -56,7 +55,6 @@ extern void _PyUnicode_Fini(void); extern void _PyCodecRegistry_Init(void); extern void _PyCodecRegistry_Fini(void); - int Py_DebugFlag; /* Needed by parser.c */ int Py_VerboseFlag; /* Needed by import.c */ int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ @@ -472,6 +470,9 @@ PyRun_InteractiveLoop(FILE *fp, char *filename) { PyObject *v; int ret; + PyCompilerFlags flags; + + flags.cf_nested_scopes = 0; v = PySys_GetObject("ps1"); if (v == NULL) { PySys_SetObject("ps1", v = PyString_FromString(">>> ")); @@ -483,7 +484,7 @@ PyRun_InteractiveLoop(FILE *fp, char *filename) Py_XDECREF(v); } for (;;) { - ret = PyRun_InteractiveOne(fp, filename); + ret = PyRun_InteractiveOneFlags(fp, filename, &flags); #ifdef Py_REF_DEBUG fprintf(stderr, "[%ld refs]\n", _Py_RefTotal); #endif @@ -499,6 +500,12 @@ PyRun_InteractiveLoop(FILE *fp, char *filename) int PyRun_InteractiveOne(FILE *fp, char *filename) { + return PyRun_InteractiveOneFlags(fp, filename, NULL); +} + +int +PyRun_InteractiveOneFlags(FILE *fp, char *filename, PyCompilerFlags *flags) +{ PyObject *m, *d, *v, *w; node *n; perrdetail err; @@ -537,7 +544,7 @@ PyRun_InteractiveOne(FILE *fp, char *filename) if (m == NULL) return -1; d = PyModule_GetDict(m); - v = run_node(n, filename, d, d); + v = run_node(n, filename, d, d, flags); if (v == NULL) { PyErr_Print(); return -1; @@ -907,7 +914,7 @@ PyObject * PyRun_String(char *str, int start, PyObject *globals, PyObject *locals) { return run_err_node(PyParser_SimpleParseString(str, start), - "", globals, locals); + "", globals, locals, NULL); } PyObject * @@ -924,23 +931,26 @@ PyRun_FileEx(FILE *fp, char *filename, int start, PyObject *globals, node *n = PyParser_SimpleParseFile(fp, filename, start); if (closeit) fclose(fp); - return run_err_node(n, filename, globals, locals); + return run_err_node(n, filename, globals, locals, NULL); } static PyObject * -run_err_node(node *n, char *filename, PyObject *globals, PyObject *locals) +run_err_node(node *n, char *filename, PyObject *globals, PyObject *locals, + PyCompilerFlags *flags) { if (n == NULL) return NULL; - return run_node(n, filename, globals, locals); + return run_node(n, filename, globals, locals, flags); } static PyObject * -run_node(node *n, char *filename, PyObject *globals, PyObject *locals) +run_node(node *n, char *filename, PyObject *globals, PyObject *locals, + PyCompilerFlags *flags) { PyCodeObject *co; PyObject *v; - co = PyNode_Compile(n, filename); + /* XXX pass sess->ss_nested_scopes to PyNode_Compile */ + co = PyNode_CompileFlags(n, filename, flags); PyNode_Free(n); if (co == NULL) return NULL; -- cgit v0.12