diff --git a/Include/pythonrun.h b/Include/pythonrun.h index 94413768110..6c6117bfe49 100644 --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -42,6 +42,8 @@ object *run_file PROTO((FILE *, char *, int, object *, object *)); object *run_err_node PROTO((int, struct _node *, char *, object *, object *)); object *run_node PROTO((struct _node *, char *, object *, object *)); +object *compile_string PROTO((char *, char *, int)); + void print_error PROTO((void)); void goaway PROTO((int)); diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 85c89f6562a..aa2979577e7 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -38,7 +38,7 @@ static struct memberlist frame_memberlist[] = { {"f_code", T_OBJECT, OFF(f_code)}, {"f_globals", T_OBJECT, OFF(f_globals)}, {"f_locals", T_OBJECT, OFF(f_locals)}, - {"f_fastlocals",T_OBJECT, OFF(f_fastlocals)}, +/* {"f_fastlocals",T_OBJECT, OFF(f_fastlocals)}, /* XXX Unsafe */ {"f_localmap", T_OBJECT, OFF(f_localmap)}, {"f_lasti", T_INT, OFF(f_lasti)}, {"f_lineno", T_INT, OFF(f_lineno)}, diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 8fd12e41927..b74b9cc0282 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -35,6 +35,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "pythonrun.h" #include "ceval.h" #include "modsupport.h" +#include "compile.h" +#include "eval.h" static object * builtin_abs(self, v) @@ -106,6 +108,29 @@ builtin_coerce(self, args) return res; } +static object * +builtin_compile(self, args) + object *self; + object *args; +{ + char *str; + char *filename; + char *startstr; + int start; + if (!getargs(args, "(sss)", &str, &filename, &startstr)) + return NULL; + if (strcmp(startstr, "exec") == 0) + start = file_input; + else if (strcmp(startstr, "eval") == 0) + start = eval_input; + else { + err_setstr(ValueError, + "compile() mode must be 'exec' or 'eval'"); + return NULL; + } + return compile_string(str, filename, start); +} + static object * builtin_dir(self, v) object *self; @@ -168,23 +193,26 @@ exec_eval(v, start) char *s; int n; if (v != NULL) { - if (is_stringobject(v)) - str = v; - else if (is_tupleobject(v) && + if (is_tupleobject(v) && ((n = gettuplesize(v)) == 2 || n == 3)) { str = gettupleitem(v, 0); globals = gettupleitem(v, 1); if (n == 3) locals = gettupleitem(v, 2); } + else + str = v; } - if (str == NULL || !is_stringobject(str) || + if (str == NULL || (!is_stringobject(str) && !is_codeobject(str)) || globals != NULL && !is_dictobject(globals) || locals != NULL && !is_dictobject(locals)) { err_setstr(TypeError, - "exec/eval arguments must be string[,dict[,dict]]"); + "exec/eval arguments must be (string|code)[,dict[,dict]]"); return NULL; } + if (is_codeobject(str)) + return eval_code((codeobject *) str, globals, locals, + (object *)NULL); s = getstringvalue(str); if (strlen(s) != getstringsize(str)) { err_setstr(ValueError, "embedded '\\0' in string arg"); @@ -305,6 +333,17 @@ builtin_hasattr(self, args) return newintobject(1L); } +static object * +builtin_id(self, args) + object *self; + object *args; +{ + object *v; + if (!getargs(args, "O", &v)) + return NULL; + return newintobject((long)v); +} + static object * builtin_setattr(self, args) object *self; @@ -713,6 +752,7 @@ static struct methodlist builtin_methods[] = { {"chr", builtin_chr}, {"cmp", builtin_cmp}, {"coerce", builtin_coerce}, + {"compile", builtin_compile}, {"dir", builtin_dir}, {"divmod", builtin_divmod}, {"eval", builtin_eval}, @@ -723,6 +763,7 @@ static struct methodlist builtin_methods[] = { {"hasattr", builtin_hasattr}, {"hash", builtin_hash}, {"hex", builtin_hex}, + {"id", builtin_id}, {"input", builtin_input}, {"int", builtin_int}, {"len", builtin_len}, diff --git a/Python/ceval.c b/Python/ceval.c index 45d0a6ac41b..cdd71a89d9c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -45,6 +45,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define CHECKEXC 1 /* Double-check exception checking */ #endif +#define DEBUG + + /* Forward declarations */ #ifdef LLTRACE @@ -82,6 +85,7 @@ static object *cmp_outcome PROTO((int, object *, object *)); static int import_from PROTO((object *, object *, object *)); static object *build_class PROTO((object *, object *)); static void locals_2_fast PROTO((frameobject *, int)); +static void fast_2_locals PROTO((frameobject *)); /* Pointer to current frame, used to link new frames to */ @@ -178,6 +182,7 @@ eval_code(co, globals, locals, arg) object *trace = NULL; /* Trace function or NULL */ object *retval; /* Return value iff why == WHY_RETURN */ char *name; /* Name used by some instructions */ + int needmerge = 0; #ifdef LLTRACE int lltrace = dictlookup(globals, "__lltrace__") != NULL; #endif @@ -217,6 +222,18 @@ eval_code(co, globals, locals, arg) #define POP() BASIC_POP() #endif + if (globals == NULL) { + globals = getglobals(); + if (locals == NULL) { + locals = getlocals(); + needmerge = 1; + } + } + else { + if (locals == NULL) + locals = globals; + } + f = newframeobject( current_frame, /*back*/ co, /*code*/ @@ -1328,11 +1345,17 @@ eval_code(co, globals, locals, arg) why = WHY_EXCEPTION; } } + + if (fastlocals && (f->ob_refcnt > 1 || f->f_locals->ob_refcnt > 2)) + fast_2_locals(f); /* Restore previous frame and release the current one */ current_frame = f->f_back; DECREF(f); + + if (needmerge) + locals_2_fast(current_frame, 1); return retval; } @@ -1417,7 +1440,9 @@ call_trace(p_trace, p_newtrace, f, msg, arg) INCREF(arg); settupleitem(arglist, 2, arg); tracing++; + fast_2_locals(f); res = call_object(*p_trace, arglist); + locals_2_fast(f, 1); tracing--; cleanup: XDECREF(arglist); @@ -1447,24 +1472,25 @@ call_trace(p_trace, p_newtrace, f, msg, arg) } } -object * -getlocals() -{ - /* Merge f->f_fastlocals into f->f_locals, then return the latter */ +static void +fast_2_locals(f) frameobject *f; +{ + /* Merge f->f_fastlocals into f->f_locals */ object *locals, *fast, *map; + object *error_type, *error_value; int i; - f = current_frame; if (f == NULL) - return NULL; + return; locals = f->f_locals; fast = f->f_fastlocals; map = f->f_localmap; if (locals == NULL || fast == NULL || map == NULL) - return locals; + return; if (!is_dictobject(locals) || !is_listobject(fast) || !is_dictobject(map)) - return locals; + return; + err_get(&error_type, &error_value); i = getdictsize(map); while (--i >= 0) { object *key; @@ -1488,7 +1514,7 @@ getlocals() err_clear(); } } - return locals; + err_setval(error_type, error_value); } static void @@ -1538,6 +1564,15 @@ mergelocals() locals_2_fast(current_frame, 1); } +object * +getlocals() +{ + if (current_frame == NULL) + return NULL; + fast_2_locals(current_frame); + return current_frame->f_locals; +} + object * getglobals() { diff --git a/Python/pythonrun.c b/Python/pythonrun.c index c387c629966..98008b4b9ba 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -263,7 +263,7 @@ object * run_string(str, start, globals, locals) char *str; int start; - /*dict*/object *globals, *locals; + object *globals, *locals; { node *n; int err; @@ -276,7 +276,7 @@ run_file(fp, filename, start, globals, locals) FILE *fp; char *filename; int start; - /*dict*/object *globals, *locals; + object *globals, *locals; { node *n; int err; @@ -289,7 +289,7 @@ run_err_node(err, n, filename, globals, locals) int err; node *n; char *filename; - /*dict*/object *globals, *locals; + object *globals, *locals; { if (err != E_DONE) { err_input(err); @@ -302,25 +302,9 @@ object * run_node(n, filename, globals, locals) node *n; char *filename; - /*dict*/object *globals, *locals; + object *globals, *locals; { - object *res; - int needmerge = 0; - if (globals == NULL) { - globals = getglobals(); - if (locals == NULL) { - locals = getlocals(); - needmerge = 1; - } - } - else { - if (locals == NULL) - locals = globals; - } - res = eval_node(n, filename, globals, locals); - if (needmerge) - mergelocals(); - return res; + return eval_node(n, filename, globals, locals); } object * @@ -341,6 +325,25 @@ eval_node(n, filename, globals, locals) return v; } +object * +compile_string(str, filename, start) + char *str; + char *filename; + int start; +{ + node *n; + int err; + codeobject *co; + err = parse_string(str, start, &n); + if (err != E_DONE) { + err_input(err); + return NULL; + } + co = compile(n, filename); + freetree(n); + return (object *)co; +} + /* Simplified interface to parsefile */ int