* 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:
Guido van Rossum 1993-10-18 17:06:59 +00:00
parent cacd9579d4
commit db3165e655
9 changed files with 600 additions and 451 deletions

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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},

View File

@ -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;
}

View File

@ -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