keyword arguments and faster calls
This commit is contained in:
parent
11a3f0c2bc
commit
681d79aaf3
|
@ -80,15 +80,20 @@ builtin_apply(self, args)
|
||||||
object *self;
|
object *self;
|
||||||
object *args;
|
object *args;
|
||||||
{
|
{
|
||||||
object *func, *alist;
|
object *func, *alist, *kwdict = NULL;
|
||||||
|
|
||||||
if (!newgetargs(args, "OO:apply", &func, &alist))
|
if (!newgetargs(args, "O|OO:apply", &func, &alist, &kwdict))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!is_tupleobject(alist)) {
|
if (alist != NULL && !is_tupleobject(alist)) {
|
||||||
err_setstr(TypeError, "apply() 2nd argument must be tuple");
|
err_setstr(TypeError, "apply() 2nd argument must be tuple");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return call_object(func, alist);
|
if (kwdict != NULL && !is_dictobject(kwdict)) {
|
||||||
|
err_setstr(TypeError,
|
||||||
|
"apply() 3rd argument must be dictionary");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyEval_CallObjectWithKeywords(func, alist, kwdict);
|
||||||
}
|
}
|
||||||
|
|
||||||
static object *
|
static object *
|
||||||
|
@ -373,8 +378,7 @@ builtin_eval(self, args)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (is_codeobject(cmd))
|
if (is_codeobject(cmd))
|
||||||
return eval_code((codeobject *) cmd, globals, locals,
|
return eval_code((codeobject *) cmd, globals, locals);
|
||||||
(object *)NULL, (object *)NULL);
|
|
||||||
if (!is_stringobject(cmd)) {
|
if (!is_stringobject(cmd)) {
|
||||||
err_setstr(TypeError,
|
err_setstr(TypeError,
|
||||||
"eval() argument 1 must be string or code object");
|
"eval() argument 1 must be string or code object");
|
||||||
|
|
839
Python/ceval.c
839
Python/ceval.c
File diff suppressed because it is too large
Load Diff
492
Python/compile.c
492
Python/compile.c
|
@ -25,8 +25,14 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
/* Compile an expression node to intermediate code */
|
/* Compile an expression node to intermediate code */
|
||||||
|
|
||||||
/* XXX TO DO:
|
/* XXX TO DO:
|
||||||
XXX Compute maximum needed stack sizes while compiling
|
XXX Compute maximum needed stack sizes while compiling;
|
||||||
|
XXX then frame object can be one malloc and no stack checks are needed
|
||||||
|
XXX add __doc__ attribute == co_doc to code object attributes
|
||||||
|
XXX don't execute doc string
|
||||||
XXX Generate simple jump for break/return outside 'try...finally'
|
XXX Generate simple jump for break/return outside 'try...finally'
|
||||||
|
XXX get rid of SET_LINENO instructions, use JAR's table trick
|
||||||
|
XXX (need an option to put them back in, for debugger!)
|
||||||
|
XXX other JAR tricks?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "allobjects.h"
|
#include "allobjects.h"
|
||||||
|
@ -44,9 +50,13 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#define OFF(x) offsetof(codeobject, x)
|
#define OFF(x) offsetof(codeobject, x)
|
||||||
|
|
||||||
static struct memberlist code_memberlist[] = {
|
static struct memberlist code_memberlist[] = {
|
||||||
|
{"co_argcount", T_INT, OFF(co_argcount), READONLY},
|
||||||
|
{"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
|
||||||
|
{"co_flags", T_INT, OFF(co_flags), READONLY},
|
||||||
{"co_code", T_OBJECT, OFF(co_code), READONLY},
|
{"co_code", T_OBJECT, OFF(co_code), READONLY},
|
||||||
{"co_consts", T_OBJECT, OFF(co_consts), READONLY},
|
{"co_consts", T_OBJECT, OFF(co_consts), READONLY},
|
||||||
{"co_names", T_OBJECT, OFF(co_names), READONLY},
|
{"co_names", T_OBJECT, OFF(co_names), READONLY},
|
||||||
|
{"co_varnames", T_OBJECT, OFF(co_varnames), READONLY},
|
||||||
{"co_filename", T_OBJECT, OFF(co_filename), READONLY},
|
{"co_filename", T_OBJECT, OFF(co_filename), READONLY},
|
||||||
{"co_name", T_OBJECT, OFF(co_name), READONLY},
|
{"co_name", T_OBJECT, OFF(co_name), READONLY},
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
|
@ -69,6 +79,7 @@ code_dealloc(co)
|
||||||
XDECREF(co->co_names);
|
XDECREF(co->co_names);
|
||||||
XDECREF(co->co_filename);
|
XDECREF(co->co_filename);
|
||||||
XDECREF(co->co_name);
|
XDECREF(co->co_name);
|
||||||
|
XDECREF(co->co_varnames);
|
||||||
DEL(co);
|
DEL(co);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,11 +108,19 @@ code_compare(co, cp)
|
||||||
codeobject *co, *cp;
|
codeobject *co, *cp;
|
||||||
{
|
{
|
||||||
int cmp;
|
int cmp;
|
||||||
|
cmp = cp->co_argcount - cp->co_argcount;
|
||||||
|
if (cmp) return cmp;
|
||||||
|
cmp = cp->co_nlocals - cp->co_nlocals;
|
||||||
|
if (cmp) return cmp;
|
||||||
|
cmp = cp->co_flags - cp->co_flags;
|
||||||
|
if (cmp) return cmp;
|
||||||
cmp = cmpobject((object *)co->co_code, (object *)cp->co_code);
|
cmp = cmpobject((object *)co->co_code, (object *)cp->co_code);
|
||||||
if (cmp) return cmp;
|
if (cmp) return cmp;
|
||||||
cmp = cmpobject(co->co_consts, cp->co_consts);
|
cmp = cmpobject(co->co_consts, cp->co_consts);
|
||||||
if (cmp) return cmp;
|
if (cmp) return cmp;
|
||||||
cmp = cmpobject(co->co_names, cp->co_names);
|
cmp = cmpobject(co->co_names, cp->co_names);
|
||||||
|
if (cmp) return cmp;
|
||||||
|
cmp = cmpobject(co->co_varnames, cp->co_varnames);
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,14 +128,17 @@ static long
|
||||||
code_hash(co)
|
code_hash(co)
|
||||||
codeobject *co;
|
codeobject *co;
|
||||||
{
|
{
|
||||||
long h, h1, h2, h3;
|
long h, h1, h2, h3, h4;
|
||||||
h1 = hashobject((object *)co->co_code);
|
h1 = hashobject((object *)co->co_code);
|
||||||
if (h1 == -1) return -1;
|
if (h1 == -1) return -1;
|
||||||
h2 = hashobject(co->co_consts);
|
h2 = hashobject(co->co_consts);
|
||||||
if (h2 == -1) return -1;
|
if (h2 == -1) return -1;
|
||||||
h3 = hashobject(co->co_names);
|
h3 = hashobject(co->co_names);
|
||||||
if (h3 == -1) return -1;
|
if (h3 == -1) return -1;
|
||||||
h = h1 ^ h2 ^ h3;
|
h4 = hashobject(co->co_varnames);
|
||||||
|
if (h4 == -1) return -1;
|
||||||
|
h = h1 ^ h2 ^ h3 ^ h4 ^
|
||||||
|
co->co_argcount ^ co->co_nlocals ^ co->co_flags;
|
||||||
if (h == -1) h = -2;
|
if (h == -1) h = -2;
|
||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
@ -140,67 +162,64 @@ typeobject Codetype = {
|
||||||
};
|
};
|
||||||
|
|
||||||
codeobject *
|
codeobject *
|
||||||
newcodeobject(code, consts, names, filename, name)
|
newcodeobject(argcount, nlocals, flags,
|
||||||
|
code, consts, names, varnames, filename, name)
|
||||||
|
int argcount;
|
||||||
|
int nlocals;
|
||||||
|
int flags;
|
||||||
object *code;
|
object *code;
|
||||||
object *consts;
|
object *consts;
|
||||||
object *names;
|
object *names;
|
||||||
|
object *varnames;
|
||||||
object *filename;
|
object *filename;
|
||||||
object *name;
|
object *name;
|
||||||
{
|
{
|
||||||
codeobject *co;
|
codeobject *co;
|
||||||
int i;
|
int i;
|
||||||
/* Check argument types */
|
/* Check argument types */
|
||||||
if (code == NULL || !is_stringobject(code) ||
|
if (argcount < 0 || nlocals < 0 ||
|
||||||
consts == NULL ||
|
code == NULL || !is_stringobject(code) ||
|
||||||
names == NULL ||
|
consts == NULL || !is_tupleobject(consts) ||
|
||||||
name == NULL || !(is_stringobject(name) || name == None)) {
|
names == NULL || !is_tupleobject(names) ||
|
||||||
|
varnames == NULL || !is_tupleobject(varnames) ||
|
||||||
|
name == NULL || !is_stringobject(name) ||
|
||||||
|
filename == NULL || !is_stringobject(filename)) {
|
||||||
err_badcall();
|
err_badcall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Allow two lists instead of two tuples */
|
/* Make sure names and varnames are all strings */
|
||||||
if (is_listobject(consts) && is_listobject(names)) {
|
|
||||||
consts = listtuple(consts);
|
|
||||||
if (consts == NULL)
|
|
||||||
return NULL;
|
|
||||||
names = listtuple(names);
|
|
||||||
if (names == NULL) {
|
|
||||||
DECREF(consts);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!is_tupleobject(consts) && !is_tupleobject(names)) {
|
|
||||||
err_badcall();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
INCREF(consts);
|
|
||||||
INCREF(names);
|
|
||||||
}
|
|
||||||
/* Make sure the list of names contains only strings */
|
|
||||||
for (i = gettuplesize(names); --i >= 0; ) {
|
for (i = gettuplesize(names); --i >= 0; ) {
|
||||||
object *v = gettupleitem(names, i);
|
object *v = gettupleitem(names, i);
|
||||||
if (v == NULL || !is_stringobject(v)) {
|
if (v == NULL || !is_stringobject(v)) {
|
||||||
DECREF(consts);
|
err_badcall();
|
||||||
DECREF(names);
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = gettuplesize(varnames); --i >= 0; ) {
|
||||||
|
object *v = gettupleitem(varnames, i);
|
||||||
|
if (v == NULL || !is_stringobject(v)) {
|
||||||
err_badcall();
|
err_badcall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
co = NEWOBJ(codeobject, &Codetype);
|
co = NEWOBJ(codeobject, &Codetype);
|
||||||
if (co != NULL) {
|
if (co != NULL) {
|
||||||
|
co->co_argcount = argcount;
|
||||||
|
co->co_nlocals = nlocals;
|
||||||
|
co->co_flags = flags;
|
||||||
INCREF(code);
|
INCREF(code);
|
||||||
co->co_code = (stringobject *)code;
|
co->co_code = (stringobject *)code;
|
||||||
|
INCREF(consts);
|
||||||
co->co_consts = consts;
|
co->co_consts = consts;
|
||||||
|
INCREF(names);
|
||||||
co->co_names = names;
|
co->co_names = names;
|
||||||
|
INCREF(varnames);
|
||||||
|
co->co_varnames = varnames;
|
||||||
INCREF(filename);
|
INCREF(filename);
|
||||||
co->co_filename = filename;
|
co->co_filename = filename;
|
||||||
INCREF(name);
|
INCREF(name);
|
||||||
co->co_name = name;
|
co->co_name = name;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
DECREF(consts);
|
|
||||||
DECREF(names);
|
|
||||||
}
|
|
||||||
return co;
|
return co;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +232,12 @@ struct compiling {
|
||||||
object *c_code; /* string */
|
object *c_code; /* string */
|
||||||
object *c_consts; /* list of objects */
|
object *c_consts; /* list of objects */
|
||||||
object *c_names; /* list of strings (names) */
|
object *c_names; /* list of strings (names) */
|
||||||
object *c_globals; /* dictionary */
|
object *c_globals; /* dictionary (value=None) */
|
||||||
|
object *c_locals; /* dictionary (value=localID) */
|
||||||
|
object *c_varnames; /* list (inverse of c_locals) */
|
||||||
|
int c_nlocals; /* index of next local */
|
||||||
|
int c_argcount; /* number of top-level arguments */
|
||||||
|
int c_flags; /* same as co_flags */
|
||||||
int c_nexti; /* index into c_code */
|
int c_nexti; /* index into c_code */
|
||||||
int c_errors; /* counts errors occurred */
|
int c_errors; /* counts errors occurred */
|
||||||
int c_infunction; /* set when compiling a function */
|
int c_infunction; /* set when compiling a function */
|
||||||
|
@ -257,7 +281,7 @@ block_pop(c, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Prototypes */
|
/* Prototype forward declarations */
|
||||||
|
|
||||||
static int com_init PROTO((struct compiling *, char *));
|
static int com_init PROTO((struct compiling *, char *));
|
||||||
static void com_free PROTO((struct compiling *));
|
static void com_free PROTO((struct compiling *));
|
||||||
|
@ -273,7 +297,8 @@ static int com_addconst PROTO((struct compiling *, object *));
|
||||||
static int com_addname PROTO((struct compiling *, object *));
|
static int com_addname PROTO((struct compiling *, object *));
|
||||||
static void com_addopname PROTO((struct compiling *, int, node *));
|
static void com_addopname PROTO((struct compiling *, int, node *));
|
||||||
static void com_list PROTO((struct compiling *, node *, int));
|
static void com_list PROTO((struct compiling *, node *, int));
|
||||||
static int com_argdefs PROTO((struct compiling *, node *, int *));
|
static int com_argdefs PROTO((struct compiling *, node *));
|
||||||
|
static int com_newlocal PROTO((struct compiling *, char *));
|
||||||
|
|
||||||
static int
|
static int
|
||||||
com_init(c, filename)
|
com_init(c, filename)
|
||||||
|
@ -288,6 +313,13 @@ com_init(c, filename)
|
||||||
goto fail_1;
|
goto fail_1;
|
||||||
if ((c->c_globals = newdictobject()) == NULL)
|
if ((c->c_globals = newdictobject()) == NULL)
|
||||||
goto fail_0;
|
goto fail_0;
|
||||||
|
if ((c->c_locals = newdictobject()) == NULL)
|
||||||
|
goto fail_00;
|
||||||
|
if ((c->c_varnames = newlistobject(0)) == NULL)
|
||||||
|
goto fail_000;
|
||||||
|
c->c_nlocals = 0;
|
||||||
|
c->c_argcount = 0;
|
||||||
|
c->c_flags = 0;
|
||||||
c->c_nexti = 0;
|
c->c_nexti = 0;
|
||||||
c->c_errors = 0;
|
c->c_errors = 0;
|
||||||
c->c_infunction = 0;
|
c->c_infunction = 0;
|
||||||
|
@ -299,6 +331,10 @@ com_init(c, filename)
|
||||||
c->c_name = "?";
|
c->c_name = "?";
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
fail_000:
|
||||||
|
DECREF(c->c_locals);
|
||||||
|
fail_00:
|
||||||
|
DECREF(c->c_globals);
|
||||||
fail_0:
|
fail_0:
|
||||||
DECREF(c->c_names);
|
DECREF(c->c_names);
|
||||||
fail_1:
|
fail_1:
|
||||||
|
@ -317,6 +353,8 @@ com_free(c)
|
||||||
XDECREF(c->c_consts);
|
XDECREF(c->c_consts);
|
||||||
XDECREF(c->c_names);
|
XDECREF(c->c_names);
|
||||||
XDECREF(c->c_globals);
|
XDECREF(c->c_globals);
|
||||||
|
XDECREF(c->c_locals);
|
||||||
|
XDECREF(c->c_varnames);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -333,6 +371,7 @@ com_addbyte(c, byte)
|
||||||
int byte;
|
int byte;
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
/*fprintf(stderr, "%3d: %3d\n", c->c_nexti, byte);*/
|
||||||
if (byte < 0 || byte > 255) {
|
if (byte < 0 || byte > 255) {
|
||||||
/*
|
/*
|
||||||
fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
|
fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
|
||||||
|
@ -1221,8 +1260,7 @@ com_test(c, n)
|
||||||
if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
|
if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
|
||||||
object *v;
|
object *v;
|
||||||
int i;
|
int i;
|
||||||
int argcount;
|
int ndefs = com_argdefs(c, CHILD(n, 0));
|
||||||
int ndefs = com_argdefs(c, CHILD(n, 0), &argcount);
|
|
||||||
v = (object *) compile(CHILD(n, 0), c->c_filename);
|
v = (object *) compile(CHILD(n, 0), c->c_filename);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
c->c_errors++;
|
c->c_errors++;
|
||||||
|
@ -1233,9 +1271,7 @@ com_test(c, n)
|
||||||
DECREF(v);
|
DECREF(v);
|
||||||
}
|
}
|
||||||
com_addoparg(c, LOAD_CONST, i);
|
com_addoparg(c, LOAD_CONST, i);
|
||||||
com_addbyte(c, BUILD_FUNCTION);
|
com_addoparg(c, MAKE_FUNCTION, ndefs);
|
||||||
if (ndefs > 0)
|
|
||||||
com_addoparg(c, SET_FUNC_ARGS, argcount);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int anchor = 0;
|
int anchor = 0;
|
||||||
|
@ -1537,16 +1573,12 @@ com_raise_stmt(c, n)
|
||||||
{
|
{
|
||||||
REQ(n, raise_stmt); /* 'raise' test [',' test [',' test]] */
|
REQ(n, raise_stmt); /* 'raise' test [',' test [',' test]] */
|
||||||
com_node(c, CHILD(n, 1));
|
com_node(c, CHILD(n, 1));
|
||||||
if (NCH(n) > 3)
|
if (NCH(n) > 3) {
|
||||||
com_node(c, CHILD(n, 3));
|
com_node(c, CHILD(n, 3));
|
||||||
else
|
if (NCH(n) > 5)
|
||||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
com_node(c, CHILD(n, 5));
|
||||||
if (NCH(n) > 5) {
|
|
||||||
com_node(c, CHILD(n, 5));
|
|
||||||
com_addoparg(c, RAISE_VARARGS, 3);
|
|
||||||
}
|
}
|
||||||
else
|
com_addoparg(c, RAISE_VARARGS, NCH(n)/2);
|
||||||
com_addbyte(c, RAISE_EXCEPTION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1585,11 +1617,69 @@ com_global_stmt(c, n)
|
||||||
REQ(n, global_stmt);
|
REQ(n, global_stmt);
|
||||||
/* 'global' NAME (',' NAME)* */
|
/* 'global' NAME (',' NAME)* */
|
||||||
for (i = 1; i < NCH(n); i += 2) {
|
for (i = 1; i < NCH(n); i += 2) {
|
||||||
if (dictinsert(c->c_globals, STR(CHILD(n, i)), None) != 0)
|
char *s = STR(CHILD(n, i));
|
||||||
|
if (dictlookup(c->c_locals, s) != NULL) {
|
||||||
|
err_setstr(SyntaxError, "name is local and global");
|
||||||
|
c->c_errors++;
|
||||||
|
}
|
||||||
|
else if (dictinsert(c->c_globals, s, None) != 0)
|
||||||
c->c_errors++;
|
c->c_errors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
com_newlocal_o(c, nameval)
|
||||||
|
struct compiling *c;
|
||||||
|
object *nameval;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
object *ival;
|
||||||
|
if (getlistsize(c->c_varnames) != c->c_nlocals) {
|
||||||
|
/* This is usually caused by an error on a previous call */
|
||||||
|
if (c->c_errors == 0) {
|
||||||
|
err_setstr(SystemError, "mixed up var name/index");
|
||||||
|
c->c_errors++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ival = newintobject(i = c->c_nlocals++);
|
||||||
|
if (ival == NULL)
|
||||||
|
c->c_errors++;
|
||||||
|
else if (mappinginsert(c->c_locals, nameval, ival) != 0)
|
||||||
|
c->c_errors++;
|
||||||
|
else if (addlistitem(c->c_varnames, nameval) != 0)
|
||||||
|
c->c_errors++;
|
||||||
|
XDECREF(ival);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
com_addlocal_o(c, nameval)
|
||||||
|
struct compiling *c;
|
||||||
|
object *nameval;
|
||||||
|
{
|
||||||
|
object *ival = mappinglookup(c->c_locals, nameval);
|
||||||
|
if (ival != NULL)
|
||||||
|
return getintvalue(ival);
|
||||||
|
return com_newlocal_o(c, nameval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
com_newlocal(c, name)
|
||||||
|
struct compiling *c;
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
object *nameval = newstringobject(name);
|
||||||
|
int i;
|
||||||
|
if (nameval == NULL) {
|
||||||
|
c->c_errors++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
i = com_newlocal_o(c, nameval);
|
||||||
|
DECREF(nameval);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
#define strequ(a, b) (strcmp((a), (b)) == 0)
|
#define strequ(a, b) (strcmp((a), (b)) == 0)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2019,12 +2109,11 @@ com_continue_stmt(c, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
com_argdefs(c, n, argcount_return)
|
com_argdefs(c, n)
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
node *n;
|
node *n;
|
||||||
int *argcount_return;
|
|
||||||
{
|
{
|
||||||
int i, nch, nargs, ndefs, star;
|
int i, nch, nargs, ndefs;
|
||||||
if (TYPE(n) == lambdef) {
|
if (TYPE(n) == lambdef) {
|
||||||
/* lambdef: 'lambda' [varargslist] ':' test */
|
/* lambdef: 'lambda' [varargslist] ':' test */
|
||||||
n = CHILD(n, 1);
|
n = CHILD(n, 1);
|
||||||
|
@ -2036,14 +2125,13 @@ com_argdefs(c, n, argcount_return)
|
||||||
n = CHILD(n, 1);
|
n = CHILD(n, 1);
|
||||||
}
|
}
|
||||||
if (TYPE(n) != varargslist)
|
if (TYPE(n) != varargslist)
|
||||||
return -1;
|
return 0;
|
||||||
/* varargslist:
|
/* varargslist:
|
||||||
(fpdef ['=' test] ',')* '*' NAME ....... |
|
(fpdef ['=' test] ',')* '*' ....... |
|
||||||
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
|
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
|
||||||
nch = NCH(n);
|
nch = NCH(n);
|
||||||
nargs = 0;
|
nargs = 0;
|
||||||
ndefs = 0;
|
ndefs = 0;
|
||||||
star = 0;
|
|
||||||
for (i = 0; i < nch; i++) {
|
for (i = 0; i < nch; i++) {
|
||||||
int t;
|
int t;
|
||||||
if (TYPE(CHILD(n, i)) == STAR)
|
if (TYPE(CHILD(n, i)) == STAR)
|
||||||
|
@ -2073,11 +2161,6 @@ com_argdefs(c, n, argcount_return)
|
||||||
if (t != COMMA)
|
if (t != COMMA)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (star)
|
|
||||||
nargs ^= 0x4000;
|
|
||||||
*argcount_return = nargs;
|
|
||||||
if (ndefs > 0)
|
|
||||||
com_addoparg(c, BUILD_TUPLE, ndefs);
|
|
||||||
return ndefs;
|
return ndefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2093,12 +2176,9 @@ com_funcdef(c, n)
|
||||||
c->c_errors++;
|
c->c_errors++;
|
||||||
else {
|
else {
|
||||||
int i = com_addconst(c, v);
|
int i = com_addconst(c, v);
|
||||||
int argcount;
|
int ndefs = com_argdefs(c, n);
|
||||||
int ndefs = com_argdefs(c, n, &argcount);
|
|
||||||
com_addoparg(c, LOAD_CONST, i);
|
com_addoparg(c, LOAD_CONST, i);
|
||||||
com_addbyte(c, BUILD_FUNCTION);
|
com_addoparg(c, MAKE_FUNCTION, ndefs);
|
||||||
if (ndefs > 0)
|
|
||||||
com_addoparg(c, SET_FUNC_ARGS, argcount);
|
|
||||||
com_addopname(c, STORE_NAME, CHILD(n, 1));
|
com_addopname(c, STORE_NAME, CHILD(n, 1));
|
||||||
DECREF(v);
|
DECREF(v);
|
||||||
}
|
}
|
||||||
|
@ -2145,8 +2225,8 @@ com_classdef(c, n)
|
||||||
else {
|
else {
|
||||||
i = com_addconst(c, v);
|
i = com_addconst(c, v);
|
||||||
com_addoparg(c, LOAD_CONST, i);
|
com_addoparg(c, LOAD_CONST, i);
|
||||||
com_addbyte(c, BUILD_FUNCTION);
|
com_addoparg(c, MAKE_FUNCTION, 0);
|
||||||
com_addbyte(c, UNARY_CALL);
|
com_addoparg(c, CALL_FUNCTION, 0);
|
||||||
com_addbyte(c, BUILD_CLASS);
|
com_addbyte(c, BUILD_CLASS);
|
||||||
com_addopname(c, STORE_NAME, CHILD(n, 1));
|
com_addopname(c, STORE_NAME, CHILD(n, 1));
|
||||||
DECREF(v);
|
DECREF(v);
|
||||||
|
@ -2312,7 +2392,7 @@ com_fpdef(c, n)
|
||||||
if (TYPE(CHILD(n, 0)) == LPAR)
|
if (TYPE(CHILD(n, 0)) == LPAR)
|
||||||
com_fplist(c, CHILD(n, 1));
|
com_fplist(c, CHILD(n, 1));
|
||||||
else
|
else
|
||||||
com_addopname(c, STORE_NAME, CHILD(n, 0));
|
com_addoparg(c, STORE_FAST, com_newlocal(c, STR(CHILD(n, 0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2337,53 +2417,87 @@ com_arglist(c, n)
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
node *n;
|
node *n;
|
||||||
{
|
{
|
||||||
int nch, op, nargs, i, t;
|
int nch, i;
|
||||||
|
int complex = 0;
|
||||||
REQ(n, varargslist);
|
REQ(n, varargslist);
|
||||||
/* varargslist:
|
/* varargslist:
|
||||||
(fpdef ['=' test] ',')* '*' NAME ..... |
|
(fpdef ['=' test] ',')* (fpdef ['=' test] | '*' .....) */
|
||||||
fpdef ['=' test] (',' fpdef ['=' test])* [','] */
|
|
||||||
nch = NCH(n);
|
nch = NCH(n);
|
||||||
op = UNPACK_ARG;
|
/* Enter all arguments in table of locals */
|
||||||
nargs = 0;
|
|
||||||
for (i = 0; i < nch; i++) {
|
for (i = 0; i < nch; i++) {
|
||||||
if (TYPE(CHILD(n, i)) == STAR) {
|
node *ch = CHILD(n, i);
|
||||||
nch = i;
|
node *fp;
|
||||||
if (TYPE(CHILD(n, i+1)) != STAR)
|
char *name;
|
||||||
op = UNPACK_VARARG;
|
if (TYPE(ch) == STAR)
|
||||||
break;
|
break;
|
||||||
|
REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
|
||||||
|
fp = CHILD(ch, 0);
|
||||||
|
if (TYPE(fp) == NAME)
|
||||||
|
name = STR(fp);
|
||||||
|
else {
|
||||||
|
name = "";
|
||||||
|
complex= 1;
|
||||||
}
|
}
|
||||||
nargs++;
|
com_newlocal(c, name);
|
||||||
i++;
|
c->c_argcount++;
|
||||||
if (i >= nch)
|
if (++i >= nch)
|
||||||
break;
|
break;
|
||||||
t = TYPE(CHILD(n, i));
|
ch = CHILD(n, i);
|
||||||
if (t == EQUAL) {
|
if (TYPE(ch) == EQUAL)
|
||||||
i += 2;
|
i += 2;
|
||||||
if (i >= nch)
|
else
|
||||||
break;
|
REQ(ch, COMMA);
|
||||||
t = TYPE(CHILD(n, i));
|
|
||||||
}
|
|
||||||
if (t != COMMA)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
com_addoparg(c, op, nargs);
|
/* Handle *arguments */
|
||||||
for (i = 0; i < nch; i++) {
|
if (i < nch) {
|
||||||
com_fpdef(c, CHILD(n, i));
|
node *ch;
|
||||||
i++;
|
ch = CHILD(n, i);
|
||||||
if (i >= nch)
|
REQ(ch, STAR);
|
||||||
break;
|
ch = CHILD(n, i+1);
|
||||||
t = TYPE(CHILD(n, i));
|
if (TYPE(ch) == NAME) {
|
||||||
if (t == EQUAL) {
|
c->c_flags |= CO_VARARGS;
|
||||||
i += 2;
|
i += 3;
|
||||||
if (i >= nch)
|
com_newlocal(c, STR(ch));
|
||||||
break;
|
}
|
||||||
t = TYPE(CHILD(n, i));
|
}
|
||||||
|
/* Handle **keywords */
|
||||||
|
if (i < nch) {
|
||||||
|
node *ch;
|
||||||
|
ch = CHILD(n, i);
|
||||||
|
REQ(ch, STAR);
|
||||||
|
ch = CHILD(n, i+1);
|
||||||
|
REQ(ch, STAR);
|
||||||
|
ch = CHILD(n, i+2);
|
||||||
|
REQ(ch, NAME);
|
||||||
|
c->c_flags |= CO_VARKEYWORDS;
|
||||||
|
com_newlocal(c, STR(ch));
|
||||||
|
}
|
||||||
|
if (complex) {
|
||||||
|
/* Generate code for complex arguments only after
|
||||||
|
having counted the simple arguments */
|
||||||
|
int ilocal = 0;
|
||||||
|
for (i = 0; i < nch; i++) {
|
||||||
|
node *ch = CHILD(n, i);
|
||||||
|
node *fp;
|
||||||
|
char *name;
|
||||||
|
if (TYPE(ch) == STAR)
|
||||||
|
break;
|
||||||
|
REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
|
||||||
|
fp = CHILD(ch, 0);
|
||||||
|
if (TYPE(fp) != NAME) {
|
||||||
|
com_addoparg(c, LOAD_FAST, ilocal);
|
||||||
|
com_fpdef(c, ch);
|
||||||
|
}
|
||||||
|
ilocal++;
|
||||||
|
if (++i >= nch)
|
||||||
|
break;
|
||||||
|
ch = CHILD(n, i);
|
||||||
|
if (TYPE(ch) == EQUAL)
|
||||||
|
i += 2;
|
||||||
|
else
|
||||||
|
REQ(ch, COMMA);
|
||||||
}
|
}
|
||||||
if (t != COMMA)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (op == UNPACK_VARARG)
|
|
||||||
com_addopname(c, STORE_NAME, CHILD(n, nch+1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2424,12 +2538,11 @@ compile_funcdef(c, n)
|
||||||
(void) com_addconst(c, doc);
|
(void) com_addconst(c, doc);
|
||||||
DECREF(doc);
|
DECREF(doc);
|
||||||
}
|
}
|
||||||
com_addoparg(c, RESERVE_FAST, com_addconst(c, None)); /* Patched! */
|
else
|
||||||
|
(void) com_addconst(c, None); /* No docstring */
|
||||||
ch = CHILD(n, 2); /* parameters: '(' [varargslist] ')' */
|
ch = CHILD(n, 2); /* parameters: '(' [varargslist] ')' */
|
||||||
ch = CHILD(ch, 1); /* ')' | varargslist */
|
ch = CHILD(ch, 1); /* ')' | varargslist */
|
||||||
if (TYPE(ch) == RPAR)
|
if (TYPE(ch) == varargslist)
|
||||||
com_addoparg(c, UNPACK_ARG, 0);
|
|
||||||
else
|
|
||||||
com_arglist(c, ch);
|
com_arglist(c, ch);
|
||||||
c->c_infunction = 1;
|
c->c_infunction = 1;
|
||||||
com_node(c, CHILD(n, 4));
|
com_node(c, CHILD(n, 4));
|
||||||
|
@ -2444,21 +2557,18 @@ compile_lambdef(c, n)
|
||||||
node *n;
|
node *n;
|
||||||
{
|
{
|
||||||
node *ch;
|
node *ch;
|
||||||
REQ(n, lambdef); /* lambdef: 'lambda' [parameters] ':' test */
|
REQ(n, lambdef); /* lambdef: 'lambda' [varargslist] ':' test */
|
||||||
c->c_name = "<lambda>";
|
c->c_name = "<lambda>";
|
||||||
|
|
||||||
ch = CHILD(n, 1);
|
ch = CHILD(n, 1);
|
||||||
(void) com_addconst(c, None);
|
(void) com_addconst(c, None); /* No docstring */
|
||||||
if (TYPE(ch) == COLON) {
|
if (TYPE(ch) == varargslist) {
|
||||||
com_addoparg(c, UNPACK_ARG, 0);
|
|
||||||
com_node(c, CHILD(n, 2));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
com_addoparg(c, RESERVE_FAST, com_addconst(c, None));
|
|
||||||
com_arglist(c, ch);
|
com_arglist(c, ch);
|
||||||
com_node(c, CHILD(n, 3));
|
ch = CHILD(n, 3);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ch = CHILD(n, 2);
|
||||||
|
com_node(c, ch);
|
||||||
com_addbyte(c, RETURN_VALUE);
|
com_addbyte(c, RETURN_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2544,34 +2654,31 @@ compile_node(c, n)
|
||||||
The latter instructions are much faster because they don't need to
|
The latter instructions are much faster because they don't need to
|
||||||
look up the variable name in a dictionary.
|
look up the variable name in a dictionary.
|
||||||
|
|
||||||
To find all local variables, we check all STORE_NAME, IMPORT_FROM and
|
To find all local variables, we check all STORE_NAME, IMPORT_FROM
|
||||||
DELETE_NAME instructions. This yields all local variables, including
|
and DELETE_NAME instructions. This yields all local variables,
|
||||||
arguments, function definitions, class definitions and import
|
function definitions, class definitions and import statements.
|
||||||
statements.
|
Argument names have already been entered into the list by the
|
||||||
|
special processing for the argument list.
|
||||||
|
|
||||||
All remaining LOAD_NAME instructions must refer to non-local (global
|
All remaining LOAD_NAME instructions must refer to non-local (global
|
||||||
or builtin) variables, so are replaced by LOAD_GLOBAL.
|
or builtin) variables, so are replaced by LOAD_GLOBAL.
|
||||||
|
|
||||||
There are two problems: 'from foo import *' and 'exec' may introduce
|
There are two problems: 'from foo import *' and 'exec' may introduce
|
||||||
local variables that we can't know while compiling. If this is the
|
local variables that we can't know while compiling. If this is the
|
||||||
case, we don't optimize at all (this rarely happens, since exec is
|
case, we can still optimize bona fide locals (since those
|
||||||
rare, & this form of import statement is mostly used at the module
|
statements will be surrounded by fast_2_locals() and
|
||||||
level).
|
locals_2_fast()), but we can't change LOAD_NAME to LOAD_GLOBAL.
|
||||||
|
|
||||||
NB: this modifies the string object co->co_code!
|
NB: this modifies the string object c->c_code! */
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
optimize(c)
|
optimize(c)
|
||||||
struct compiling *c;
|
struct compiling *c;
|
||||||
{
|
{
|
||||||
unsigned char *next_instr, *cur_instr;
|
unsigned char *next_instr, *cur_instr;
|
||||||
object *locals;
|
|
||||||
int nlocals;
|
|
||||||
int opcode;
|
int opcode;
|
||||||
int oparg;
|
int oparg;
|
||||||
object *name;
|
object *name;
|
||||||
int fast_reserved;
|
|
||||||
object *error_type, *error_value, *error_traceback;
|
object *error_type, *error_value, *error_traceback;
|
||||||
|
|
||||||
#define NEXTOP() (*next_instr++)
|
#define NEXTOP() (*next_instr++)
|
||||||
|
@ -2579,53 +2686,33 @@ optimize(c)
|
||||||
#define GETITEM(v, i) (getlistitem((v), (i)))
|
#define GETITEM(v, i) (getlistitem((v), (i)))
|
||||||
#define GETNAMEOBJ(i) (GETITEM(c->c_names, (i)))
|
#define GETNAMEOBJ(i) (GETITEM(c->c_names, (i)))
|
||||||
|
|
||||||
locals = newdictobject();
|
|
||||||
if (locals == NULL) {
|
|
||||||
c->c_errors++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nlocals = 0;
|
|
||||||
|
|
||||||
err_fetch(&error_type, &error_value, &error_traceback);
|
err_fetch(&error_type, &error_value, &error_traceback);
|
||||||
|
|
||||||
|
c->c_flags |= CO_OPTIMIZED;
|
||||||
|
|
||||||
next_instr = (unsigned char *) getstringvalue(c->c_code);
|
next_instr = (unsigned char *) getstringvalue(c->c_code);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
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 ||
|
switch (opcode) {
|
||||||
opcode == IMPORT_FROM) {
|
case STORE_NAME:
|
||||||
object *v;
|
case DELETE_NAME:
|
||||||
name = GETNAMEOBJ(oparg);
|
case IMPORT_FROM:
|
||||||
if (dict2lookup(locals, name) != NULL)
|
com_addlocal_o(c, GETNAMEOBJ(oparg));
|
||||||
continue;
|
break;
|
||||||
err_clear();
|
case EXEC_STMT:
|
||||||
v = newintobject(nlocals);
|
c->c_flags &= ~CO_OPTIMIZED;
|
||||||
if (v == NULL) {
|
break;
|
||||||
c->c_errors++;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
nlocals++;
|
|
||||||
if (dict2insert(locals, name, v) != 0) {
|
|
||||||
DECREF(v);
|
|
||||||
c->c_errors++;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
DECREF(v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dictlookup(locals, "*") != NULL) {
|
if (dictlookup(c->c_locals, "*") != NULL)
|
||||||
/* Don't optimize anything */
|
c->c_flags &= ~CO_OPTIMIZED;
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_instr = (unsigned char *) getstringvalue(c->c_code);
|
next_instr = (unsigned char *) getstringvalue(c->c_code);
|
||||||
fast_reserved = 0;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cur_instr = next_instr;
|
cur_instr = next_instr;
|
||||||
opcode = NEXTOP();
|
opcode = NEXTOP();
|
||||||
|
@ -2633,45 +2720,17 @@ optimize(c)
|
||||||
break;
|
break;
|
||||||
if (HAS_ARG(opcode))
|
if (HAS_ARG(opcode))
|
||||||
oparg = NEXTARG();
|
oparg = NEXTARG();
|
||||||
if (opcode == RESERVE_FAST) {
|
|
||||||
int i;
|
|
||||||
object *localmap = newtupleobject(nlocals);
|
|
||||||
int pos;
|
|
||||||
object *key, *value;
|
|
||||||
if (localmap == NULL) { /* XXX mask error */
|
|
||||||
err_clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pos = 0;
|
|
||||||
while (mappinggetnext(locals, &pos, &key, &value)) {
|
|
||||||
int j;
|
|
||||||
if (!is_intobject(value))
|
|
||||||
continue;
|
|
||||||
j = getintvalue(value);
|
|
||||||
if (0 <= j && j < nlocals) {
|
|
||||||
INCREF(key);
|
|
||||||
settupleitem(localmap, j, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = com_addconst(c, localmap);
|
|
||||||
cur_instr[1] = i & 0xff;
|
|
||||||
cur_instr[2] = (i>>8) & 0xff;
|
|
||||||
fast_reserved = 1;
|
|
||||||
DECREF(localmap);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!fast_reserved)
|
|
||||||
continue;
|
|
||||||
if (opcode == LOAD_NAME ||
|
if (opcode == LOAD_NAME ||
|
||||||
opcode == STORE_NAME ||
|
opcode == STORE_NAME ||
|
||||||
opcode == DELETE_NAME) {
|
opcode == DELETE_NAME) {
|
||||||
object *v;
|
object *v;
|
||||||
int i;
|
int i;
|
||||||
name = GETNAMEOBJ(oparg);
|
name = GETNAMEOBJ(oparg);
|
||||||
v = dict2lookup(locals, name);
|
v = dict2lookup(c->c_locals, name);
|
||||||
if (v == NULL) {
|
if (v == NULL) {
|
||||||
err_clear();
|
err_clear();
|
||||||
if (opcode == LOAD_NAME)
|
if (opcode == LOAD_NAME &&
|
||||||
|
(c->c_flags&CO_OPTIMIZED))
|
||||||
cur_instr[0] = LOAD_GLOBAL;
|
cur_instr[0] = LOAD_GLOBAL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2686,10 +2745,8 @@ optimize(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
if (c->c_errors == 0)
|
||||||
err_restore(error_type, error_value, error_traceback);
|
err_restore(error_type, error_value, error_traceback);
|
||||||
err:
|
|
||||||
DECREF(locals);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
codeobject *
|
codeobject *
|
||||||
|
@ -2703,18 +2760,35 @@ compile(n, filename)
|
||||||
return NULL;
|
return NULL;
|
||||||
compile_node(&sc, n);
|
compile_node(&sc, n);
|
||||||
com_done(&sc);
|
com_done(&sc);
|
||||||
if ((TYPE(n) == funcdef || TYPE(n) == lambdef) && sc.c_errors == 0)
|
if ((TYPE(n) == funcdef || TYPE(n) == lambdef) && sc.c_errors == 0) {
|
||||||
optimize(&sc);
|
optimize(&sc);
|
||||||
|
sc.c_flags |= CO_NEWLOCALS;
|
||||||
|
}
|
||||||
|
else if (TYPE(n) == classdef)
|
||||||
|
sc.c_flags |= CO_NEWLOCALS;
|
||||||
co = NULL;
|
co = NULL;
|
||||||
if (sc.c_errors == 0) {
|
if (sc.c_errors == 0) {
|
||||||
object *v, *w;
|
object *consts, *names, *varnames, *filename, *name;
|
||||||
v = newstringobject(sc.c_filename);
|
consts = listtuple(sc.c_consts);
|
||||||
w = newstringobject(sc.c_name);
|
names = listtuple(sc.c_names);
|
||||||
if (v != NULL && w != NULL)
|
varnames = listtuple(sc.c_varnames);
|
||||||
co = newcodeobject(sc.c_code, sc.c_consts,
|
filename = newstringobject(sc.c_filename);
|
||||||
sc.c_names, v, w);
|
name = newstringobject(sc.c_name);
|
||||||
XDECREF(v);
|
if (!err_occurred())
|
||||||
XDECREF(w);
|
co = newcodeobject(sc.c_argcount,
|
||||||
|
sc.c_nlocals,
|
||||||
|
sc.c_flags,
|
||||||
|
sc.c_code,
|
||||||
|
consts,
|
||||||
|
names,
|
||||||
|
varnames,
|
||||||
|
filename,
|
||||||
|
name);
|
||||||
|
XDECREF(consts);
|
||||||
|
XDECREF(names);
|
||||||
|
XDECREF(varnames);
|
||||||
|
XDECREF(filename);
|
||||||
|
XDECREF(name);
|
||||||
}
|
}
|
||||||
com_free(&sc);
|
com_free(&sc);
|
||||||
return co;
|
return co;
|
||||||
|
|
|
@ -54,7 +54,7 @@ extern long getmtime(); /* In getmtime.c */
|
||||||
Apple MPW compiler swaps their values, botching string constants */
|
Apple MPW compiler swaps their values, botching string constants */
|
||||||
/* XXX Perhaps the magic number should be frozen and a version field
|
/* XXX Perhaps the magic number should be frozen and a version field
|
||||||
added to the .pyc file header? */
|
added to the .pyc file header? */
|
||||||
#define MAGIC (0x4127L | ((long)'\r'<<16) | ((long)'\n'<<24))
|
#define MAGIC (11913 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||||
|
|
||||||
object *import_modules; /* This becomes sys.modules */
|
object *import_modules; /* This becomes sys.modules */
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ exec_code_module(name, co)
|
||||||
if (dictinsert(d, "__builtins__", getbuiltins()) != 0)
|
if (dictinsert(d, "__builtins__", getbuiltins()) != 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
v = eval_code((codeobject *)co, d, d, d, (object *)NULL);
|
v = eval_code((codeobject *)co, d, d); /* XXX owner? */
|
||||||
if (v == NULL)
|
if (v == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
DECREF(v);
|
DECREF(v);
|
||||||
|
|
|
@ -44,7 +44,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#define TYPE_TUPLE '('
|
#define TYPE_TUPLE '('
|
||||||
#define TYPE_LIST '['
|
#define TYPE_LIST '['
|
||||||
#define TYPE_DICT '{'
|
#define TYPE_DICT '{'
|
||||||
#define TYPE_CODE 'C'
|
#define TYPE_CODE 'c'
|
||||||
#define TYPE_UNKNOWN '?'
|
#define TYPE_UNKNOWN '?'
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -187,9 +187,13 @@ w_object(v, p)
|
||||||
else if (is_codeobject(v)) {
|
else if (is_codeobject(v)) {
|
||||||
codeobject *co = (codeobject *)v;
|
codeobject *co = (codeobject *)v;
|
||||||
w_byte(TYPE_CODE, p);
|
w_byte(TYPE_CODE, p);
|
||||||
|
w_short(co->co_argcount, p);
|
||||||
|
w_short(co->co_nlocals, p);
|
||||||
|
w_short(co->co_flags, p);
|
||||||
w_object((object *)co->co_code, p);
|
w_object((object *)co->co_code, p);
|
||||||
w_object(co->co_consts, p);
|
w_object(co->co_consts, p);
|
||||||
w_object(co->co_names, p);
|
w_object(co->co_names, p);
|
||||||
|
w_object(co->co_varnames, p);
|
||||||
w_object(co->co_filename, p);
|
w_object(co->co_filename, p);
|
||||||
w_object(co->co_name, p);
|
w_object(co->co_name, p);
|
||||||
}
|
}
|
||||||
|
@ -374,14 +378,20 @@ r_object(p)
|
||||||
|
|
||||||
case TYPE_CODE:
|
case TYPE_CODE:
|
||||||
{
|
{
|
||||||
|
int argcount = r_short(p);
|
||||||
|
int nlocals = r_short(p);
|
||||||
|
int flags = r_short(p);
|
||||||
object *code = r_object(p);
|
object *code = r_object(p);
|
||||||
object *consts = r_object(p);
|
object *consts = r_object(p);
|
||||||
object *names = r_object(p);
|
object *names = r_object(p);
|
||||||
|
object *varnames = r_object(p);
|
||||||
object *filename = r_object(p);
|
object *filename = r_object(p);
|
||||||
object *name = r_object(p);
|
object *name = r_object(p);
|
||||||
if (!err_occurred()) {
|
if (!err_occurred()) {
|
||||||
v = (object *) newcodeobject(code,
|
v = (object *) newcodeobject(
|
||||||
consts, names, filename, name);
|
argcount, nlocals, flags,
|
||||||
|
code, consts, names, varnames,
|
||||||
|
filename, name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
v = NULL;
|
v = NULL;
|
||||||
|
|
|
@ -430,7 +430,7 @@ run_node(n, filename, globals, locals)
|
||||||
freetree(n);
|
freetree(n);
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
v = eval_code(co, globals, locals, (object *)NULL, (object *)NULL);
|
v = eval_code(co, globals, locals);
|
||||||
DECREF(co);
|
DECREF(co);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ run_pyc_file(fp, filename, globals, locals)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
co = (codeobject *)v;
|
co = (codeobject *)v;
|
||||||
v = eval_code(co, globals, locals, (object *)NULL, (object *)NULL);
|
v = eval_code(co, globals, locals);
|
||||||
DECREF(co);
|
DECREF(co);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -603,16 +603,9 @@ cleanup()
|
||||||
object *exitfunc = sysget("exitfunc");
|
object *exitfunc = sysget("exitfunc");
|
||||||
|
|
||||||
if (exitfunc) {
|
if (exitfunc) {
|
||||||
object *arg;
|
|
||||||
object *res;
|
object *res;
|
||||||
sysset("exitfunc", (object *)NULL);
|
sysset("exitfunc", (object *)NULL);
|
||||||
arg = newtupleobject(0);
|
res = call_object(exitfunc, (object *)NULL);
|
||||||
if (arg == NULL)
|
|
||||||
res = NULL;
|
|
||||||
else {
|
|
||||||
res = call_object(exitfunc, arg);
|
|
||||||
DECREF(arg);
|
|
||||||
}
|
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
fprintf(stderr, "Error in sys.exitfunc:\n");
|
fprintf(stderr, "Error in sys.exitfunc:\n");
|
||||||
print_error();
|
print_error();
|
||||||
|
|
|
@ -68,7 +68,10 @@ tb_dealloc(tb)
|
||||||
DEL(tb);
|
DEL(tb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static typeobject Tracebacktype = {
|
#define Tracebacktype PyTraceback_Type
|
||||||
|
#define is_tracebackobject PyTraceback_Check
|
||||||
|
|
||||||
|
typeobject Tracebacktype = {
|
||||||
OB_HEAD_INIT(&Typetype)
|
OB_HEAD_INIT(&Typetype)
|
||||||
0,
|
0,
|
||||||
"traceback",
|
"traceback",
|
||||||
|
@ -85,8 +88,6 @@ static typeobject Tracebacktype = {
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
};
|
};
|
||||||
|
|
||||||
#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
|
|
||||||
|
|
||||||
static tracebackobject *
|
static tracebackobject *
|
||||||
newtracebackobject(next, frame, lasti, lineno)
|
newtracebackobject(next, frame, lasti, lineno)
|
||||||
tracebackobject *next;
|
tracebackobject *next;
|
||||||
|
|
Loading…
Reference in New Issue