mirror of https://github.com/python/cpython
* bltinmodule.c: removed exec() built-in function.
* Grammar: add exec statement; allow testlist in expr statement. * ceval.c, compile.c, opcode.h: support exec statement; avoid optimizing locals when it is used * fileobject.{c,h}: add getfilename() internal function.
This commit is contained in:
parent
cacd9579d4
commit
db3165e655
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
# Change log:
|
# Change log:
|
||||||
|
|
||||||
|
# 18-Oct-93:
|
||||||
|
# Use testlist instead of exprlist in expr_stmt
|
||||||
|
# Add exec statement
|
||||||
|
|
||||||
# 19-May-93:
|
# 19-May-93:
|
||||||
# Add access statement
|
# Add access statement
|
||||||
|
|
||||||
|
@ -87,8 +91,8 @@ fplist: fpdef (',' fpdef)* [',']
|
||||||
|
|
||||||
stmt: simple_stmt | compound_stmt
|
stmt: simple_stmt | compound_stmt
|
||||||
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
|
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
|
||||||
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt
|
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt
|
||||||
expr_stmt: (exprlist '=')* exprlist
|
expr_stmt: (testlist '=')* testlist
|
||||||
# For assignments, additional restrictions enforced by the interpreter
|
# For assignments, additional restrictions enforced by the interpreter
|
||||||
print_stmt: 'print' (test ',')* [test]
|
print_stmt: 'print' (test ',')* [test]
|
||||||
del_stmt: 'del' exprlist
|
del_stmt: 'del' exprlist
|
||||||
|
@ -104,6 +108,7 @@ access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)*
|
||||||
accesstype: NAME+
|
accesstype: NAME+
|
||||||
# accesstype should be ('public' | 'protected' | 'private') ['read'] ['write']
|
# accesstype should be ('public' | 'protected' | 'private') ['read'] ['write']
|
||||||
# but can't be because that would create undesirable reserved words!
|
# but can't be because that would create undesirable reserved words!
|
||||||
|
exec_stmt: 'exec' expr ['in' expr [',' expr]]
|
||||||
|
|
||||||
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
|
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
|
||||||
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
|
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
|
||||||
|
|
|
@ -38,6 +38,7 @@ extern object *newfileobject PROTO((char *, char *));
|
||||||
extern object *newopenfileobject
|
extern object *newopenfileobject
|
||||||
PROTO((FILE *, char *, char *, int (*)FPROTO((FILE *))));
|
PROTO((FILE *, char *, char *, int (*)FPROTO((FILE *))));
|
||||||
extern FILE *getfilefile PROTO((object *));
|
extern FILE *getfilefile PROTO((object *));
|
||||||
|
extern object *getfilename PROTO((object *));
|
||||||
extern object *filegetline PROTO((object *, int));
|
extern object *filegetline PROTO((object *, int));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -23,29 +23,30 @@
|
||||||
#define global_stmt 278
|
#define global_stmt 278
|
||||||
#define access_stmt 279
|
#define access_stmt 279
|
||||||
#define accesstype 280
|
#define accesstype 280
|
||||||
#define compound_stmt 281
|
#define exec_stmt 281
|
||||||
#define if_stmt 282
|
#define compound_stmt 282
|
||||||
#define while_stmt 283
|
#define if_stmt 283
|
||||||
#define for_stmt 284
|
#define while_stmt 284
|
||||||
#define try_stmt 285
|
#define for_stmt 285
|
||||||
#define except_clause 286
|
#define try_stmt 286
|
||||||
#define suite 287
|
#define except_clause 287
|
||||||
#define test 288
|
#define suite 288
|
||||||
#define and_test 289
|
#define test 289
|
||||||
#define not_test 290
|
#define and_test 290
|
||||||
#define comparison 291
|
#define not_test 291
|
||||||
#define comp_op 292
|
#define comparison 292
|
||||||
#define expr 293
|
#define comp_op 293
|
||||||
#define xor_expr 294
|
#define expr 294
|
||||||
#define and_expr 295
|
#define xor_expr 295
|
||||||
#define shift_expr 296
|
#define and_expr 296
|
||||||
#define arith_expr 297
|
#define shift_expr 297
|
||||||
#define term 298
|
#define arith_expr 298
|
||||||
#define factor 299
|
#define term 299
|
||||||
#define atom 300
|
#define factor 300
|
||||||
#define trailer 301
|
#define atom 301
|
||||||
#define subscript 302
|
#define trailer 302
|
||||||
#define exprlist 303
|
#define subscript 303
|
||||||
#define testlist 304
|
#define exprlist 304
|
||||||
#define dictmaker 305
|
#define testlist 305
|
||||||
#define classdef 306
|
#define dictmaker 306
|
||||||
|
#define classdef 307
|
||||||
|
|
|
@ -78,6 +78,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#define RAISE_EXCEPTION 81
|
#define RAISE_EXCEPTION 81
|
||||||
#define LOAD_LOCALS 82
|
#define LOAD_LOCALS 82
|
||||||
#define RETURN_VALUE 83
|
#define RETURN_VALUE 83
|
||||||
|
#define LOAD_GLOBALS 84
|
||||||
|
#define EXEC_STMT 85
|
||||||
|
|
||||||
#define BUILD_FUNCTION 86
|
#define BUILD_FUNCTION 86
|
||||||
#define POP_BLOCK 87
|
#define POP_BLOCK 87
|
||||||
|
|
|
@ -51,6 +51,16 @@ getfilefile(f)
|
||||||
return ((fileobject *)f)->f_fp;
|
return ((fileobject *)f)->f_fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object *
|
||||||
|
getfilename(f)
|
||||||
|
object *f;
|
||||||
|
{
|
||||||
|
if (f == NULL || !is_fileobject(f))
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return ((fileobject *)f)->f_name;
|
||||||
|
}
|
||||||
|
|
||||||
object *
|
object *
|
||||||
newopenfileobject(fp, name, mode, close)
|
newopenfileobject(fp, name, mode, close)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
|
@ -232,14 +232,6 @@ builtin_eval(self, v)
|
||||||
return exec_eval(v, eval_input);
|
return exec_eval(v, eval_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static object *
|
|
||||||
builtin_exec(self, v)
|
|
||||||
object *self;
|
|
||||||
object *v;
|
|
||||||
{
|
|
||||||
return exec_eval(v, file_input);
|
|
||||||
}
|
|
||||||
|
|
||||||
static object *
|
static object *
|
||||||
builtin_execfile(self, v)
|
builtin_execfile(self, v)
|
||||||
object *self;
|
object *self;
|
||||||
|
@ -755,7 +747,6 @@ static struct methodlist builtin_methods[] = {
|
||||||
{"dir", builtin_dir},
|
{"dir", builtin_dir},
|
||||||
{"divmod", builtin_divmod},
|
{"divmod", builtin_divmod},
|
||||||
{"eval", builtin_eval},
|
{"eval", builtin_eval},
|
||||||
{"exec", builtin_exec},
|
|
||||||
{"execfile", builtin_execfile},
|
{"execfile", builtin_execfile},
|
||||||
{"float", builtin_float},
|
{"float", builtin_float},
|
||||||
{"getattr", builtin_getattr},
|
{"getattr", builtin_getattr},
|
||||||
|
|
|
@ -35,6 +35,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "opcode.h"
|
#include "opcode.h"
|
||||||
#include "bltinmodule.h"
|
#include "bltinmodule.h"
|
||||||
#include "traceback.h"
|
#include "traceback.h"
|
||||||
|
#include "graminit.h"
|
||||||
|
#include "pythonrun.h"
|
||||||
|
|
||||||
/* Turn this on if your compiler chokes on the big switch: */
|
/* Turn this on if your compiler chokes on the big switch: */
|
||||||
/* #define CASE_TOO_BIG 1 /**/
|
/* #define CASE_TOO_BIG 1 /**/
|
||||||
|
@ -91,6 +93,7 @@ static object *build_class PROTO((object *, object *, object *));
|
||||||
static void locals_2_fast PROTO((frameobject *, int));
|
static void locals_2_fast PROTO((frameobject *, int));
|
||||||
static void fast_2_locals PROTO((frameobject *));
|
static void fast_2_locals PROTO((frameobject *));
|
||||||
static int access_statement PROTO((object *, object *, frameobject *));
|
static int access_statement PROTO((object *, object *, frameobject *));
|
||||||
|
static int exec_statement PROTO((object *, object *, object *));
|
||||||
|
|
||||||
|
|
||||||
/* Pointer to current frame, used to link new frames to */
|
/* Pointer to current frame, used to link new frames to */
|
||||||
|
@ -713,6 +716,22 @@ eval_code(co, globals, locals, owner, arg)
|
||||||
why = WHY_RETURN;
|
why = WHY_RETURN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LOAD_GLOBALS:
|
||||||
|
v = f->f_locals;
|
||||||
|
INCREF(v);
|
||||||
|
PUSH(v);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXEC_STMT:
|
||||||
|
w = POP();
|
||||||
|
v = POP();
|
||||||
|
u = POP();
|
||||||
|
err = exec_statement(u, v, w);
|
||||||
|
DECREF(u);
|
||||||
|
DECREF(v);
|
||||||
|
DECREF(w);
|
||||||
|
break;
|
||||||
|
|
||||||
case BUILD_FUNCTION:
|
case BUILD_FUNCTION:
|
||||||
v = POP();
|
v = POP();
|
||||||
x = newfuncobject(v, f->f_globals);
|
x = newfuncobject(v, f->f_globals);
|
||||||
|
@ -2489,3 +2508,62 @@ access_statement(name, vmode, f)
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
exec_statement(prog, globals, locals)
|
||||||
|
object *prog;
|
||||||
|
object *globals;
|
||||||
|
object *locals;
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (is_tupleobject(prog) && globals == None && locals == None &&
|
||||||
|
((n = gettuplesize(prog)) == 2 || n == 3)) {
|
||||||
|
/* Backward compatibility hack */
|
||||||
|
globals = gettupleitem(prog, 1);
|
||||||
|
if (n == 3)
|
||||||
|
locals = gettupleitem(prog, 2);
|
||||||
|
prog = gettupleitem(prog, 0);
|
||||||
|
}
|
||||||
|
if (globals == None) {
|
||||||
|
globals = getglobals();
|
||||||
|
if (locals == None)
|
||||||
|
locals = getlocals();
|
||||||
|
}
|
||||||
|
else if (locals == None)
|
||||||
|
locals = globals;
|
||||||
|
if (!is_stringobject(prog) &&
|
||||||
|
!is_codeobject(prog) &&
|
||||||
|
!is_fileobject(prog)) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"exec 1st arg must be string, code or file object");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!is_dictobject(globals) || !is_dictobject(locals)) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"exec 2nd/3rd args must be dict or None");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (is_codeobject(prog)) {
|
||||||
|
if (eval_code((codeobject *) prog, globals, locals,
|
||||||
|
(object *)NULL, (object *)NULL) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (is_fileobject(prog)) {
|
||||||
|
FILE *fp = getfilefile(prog);
|
||||||
|
char *name = getstringvalue(getfilename(prog));
|
||||||
|
if (run_file(fp, name, file_input, globals, locals) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
s = getstringvalue(prog);
|
||||||
|
if (strlen(s) != getstringsize(prog)) {
|
||||||
|
err_setstr(ValueError, "embedded '\\0' in exec string");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (run_string(s, file_input, globals, locals) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -1305,7 +1305,7 @@ com_expr_stmt(c, n)
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
node *n;
|
node *n;
|
||||||
{
|
{
|
||||||
REQ(n, expr_stmt); /* exprlist ('=' exprlist)* */
|
REQ(n, expr_stmt); /* testlist ('=' testlist)* */
|
||||||
com_node(c, CHILD(n, NCH(n)-1));
|
com_node(c, CHILD(n, NCH(n)-1));
|
||||||
if (NCH(n) == 1) {
|
if (NCH(n) == 1) {
|
||||||
com_addbyte(c, PRINT_EXPR);
|
com_addbyte(c, PRINT_EXPR);
|
||||||
|
@ -1466,6 +1466,25 @@ com_access_stmt(c, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
com_exec_stmt(c, n)
|
||||||
|
struct compiling *c;
|
||||||
|
node *n;
|
||||||
|
{
|
||||||
|
REQ(n, exec_stmt);
|
||||||
|
/* exec_stmt: 'exec' expr ['in' expr [',' expr]] */
|
||||||
|
com_node(c, CHILD(n, 1));
|
||||||
|
if (NCH(n) >= 4)
|
||||||
|
com_node(c, CHILD(n, 3));
|
||||||
|
else
|
||||||
|
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||||
|
if (NCH(n) >= 6)
|
||||||
|
com_node(c, CHILD(n, 5));
|
||||||
|
else
|
||||||
|
com_addbyte(c, DUP_TOP);
|
||||||
|
com_addbyte(c, EXEC_STMT);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
com_if_stmt(c, n)
|
com_if_stmt(c, n)
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
|
@ -1909,6 +1928,9 @@ com_node(c, n)
|
||||||
case access_stmt:
|
case access_stmt:
|
||||||
com_access_stmt(c, n);
|
com_access_stmt(c, n);
|
||||||
break;
|
break;
|
||||||
|
case exec_stmt:
|
||||||
|
com_exec_stmt(c, n);
|
||||||
|
break;
|
||||||
case if_stmt:
|
case if_stmt:
|
||||||
com_if_stmt(c, n);
|
com_if_stmt(c, n);
|
||||||
break;
|
break;
|
||||||
|
@ -2183,6 +2205,8 @@ optimize(c)
|
||||||
opcode = NEXTOP();
|
opcode = NEXTOP();
|
||||||
if (opcode == STOP_CODE)
|
if (opcode == STOP_CODE)
|
||||||
break;
|
break;
|
||||||
|
if (opcode == EXEC_STMT)
|
||||||
|
goto end; /* Don't optimize if exec present */
|
||||||
if (HAS_ARG(opcode))
|
if (HAS_ARG(opcode))
|
||||||
oparg = NEXTARG();
|
oparg = NEXTARG();
|
||||||
if (opcode == STORE_NAME || opcode == DELETE_NAME ||
|
if (opcode == STORE_NAME || opcode == DELETE_NAME ||
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue