Add co_stacksize field to codeobject structure, and stacksize argument
to PyCode_New() argument list. Move MAXBLOCKS constant to conpile.h. Added accurate calculation of the actual stack size needed by the generated code. Also commented out all fprintf statements (except for a new one to diagnose stack underflow, and one in #ifdef'ed out code), and added some new TO DO suggestions (now that the stacksize is taken of the TO DO list).
This commit is contained in:
parent
3f6e408a31
commit
8b993a98db
315
Python/compile.c
315
Python/compile.c
|
@ -32,13 +32,14 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||
/* Compile an expression node to intermediate code */
|
||||
|
||||
/* XXX TO DO:
|
||||
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 add __doc__ attribute == co_doc to code object attributes?
|
||||
XXX (it's currently the first item of the co_const tuple)
|
||||
XXX Generate simple jump for break/return outside 'try...finally'
|
||||
XXX Allow 'continue' inside 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 New 1-byte opcode for loading None
|
||||
XXX New opcode for loading the initial index for a for loop
|
||||
XXX other JAR tricks?
|
||||
*/
|
||||
|
||||
|
@ -67,6 +68,7 @@ PERFORMANCE OF THIS SOFTWARE.
|
|||
static struct memberlist code_memberlist[] = {
|
||||
{"co_argcount", T_INT, OFF(co_argcount), READONLY},
|
||||
{"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
|
||||
{"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
|
||||
{"co_flags", T_INT, OFF(co_flags), READONLY},
|
||||
{"co_code", T_OBJECT, OFF(co_code), READONLY},
|
||||
{"co_consts", T_OBJECT, OFF(co_consts), READONLY},
|
||||
|
@ -177,10 +179,11 @@ typeobject Codetype = {
|
|||
};
|
||||
|
||||
codeobject *
|
||||
newcodeobject(argcount, nlocals, flags,
|
||||
newcodeobject(argcount, nlocals, stacksize, flags,
|
||||
code, consts, names, varnames, filename, name)
|
||||
int argcount;
|
||||
int nlocals;
|
||||
int stacksize;
|
||||
int flags;
|
||||
object *code;
|
||||
object *consts;
|
||||
|
@ -221,6 +224,7 @@ newcodeobject(argcount, nlocals, flags,
|
|||
if (co != NULL) {
|
||||
co->co_argcount = argcount;
|
||||
co->co_nlocals = nlocals;
|
||||
co->co_stacksize = stacksize;
|
||||
co->co_flags = flags;
|
||||
INCREF(code);
|
||||
co->co_code = (stringobject *)code;
|
||||
|
@ -241,8 +245,6 @@ newcodeobject(argcount, nlocals, flags,
|
|||
|
||||
/* Data structure used internally */
|
||||
|
||||
#define MAXBLOCKS 20 /* Max static block nesting within a function */
|
||||
|
||||
struct compiling {
|
||||
object *c_code; /* string */
|
||||
object *c_consts; /* list of objects */
|
||||
|
@ -259,11 +261,13 @@ struct compiling {
|
|||
int c_interactive; /* generating code for interactive command */
|
||||
int c_loops; /* counts nested loops */
|
||||
int c_begin; /* begin of current loop, for 'continue' */
|
||||
int c_block[MAXBLOCKS]; /* stack of block types */
|
||||
int c_block[CO_MAXBLOCKS]; /* stack of block types */
|
||||
int c_nblocks; /* current block stack level */
|
||||
char *c_filename; /* filename of current node */
|
||||
char *c_name; /* name of object (e.g. function) */
|
||||
int c_lineno; /* Current line number */
|
||||
int c_stacklevel; /* Current stack level */
|
||||
int c_maxstacklevel; /* Maximum stack level */
|
||||
#ifdef PRIVATE_NAME_MANGLING
|
||||
char *c_private; /* for private name mangling */
|
||||
#endif
|
||||
|
@ -307,7 +311,7 @@ block_push(c, type)
|
|||
struct compiling *c;
|
||||
int type;
|
||||
{
|
||||
if (c->c_nblocks >= MAXBLOCKS) {
|
||||
if (c->c_nblocks >= CO_MAXBLOCKS) {
|
||||
com_error(c, SystemError, "too many statically nested blocks");
|
||||
}
|
||||
else {
|
||||
|
@ -332,6 +336,8 @@ block_pop(c, type)
|
|||
|
||||
static int com_init PROTO((struct compiling *, char *));
|
||||
static void com_free PROTO((struct compiling *));
|
||||
static void com_push PROTO((struct compiling *, int));
|
||||
static void com_pop PROTO((struct compiling *, int));
|
||||
static void com_done PROTO((struct compiling *));
|
||||
static void com_node PROTO((struct compiling *, struct _node *));
|
||||
static void com_factor PROTO((struct compiling *, struct _node *));
|
||||
|
@ -380,6 +386,8 @@ com_init(c, filename)
|
|||
c->c_filename = filename;
|
||||
c->c_name = "?";
|
||||
c->c_lineno = 0;
|
||||
c->c_stacklevel = 0;
|
||||
c->c_maxstacklevel = 0;
|
||||
return 1;
|
||||
|
||||
fail_000:
|
||||
|
@ -408,6 +416,32 @@ com_free(c)
|
|||
XDECREF(c->c_varnames);
|
||||
}
|
||||
|
||||
static void
|
||||
com_push(c, n)
|
||||
struct compiling *c;
|
||||
int n;
|
||||
{
|
||||
c->c_stacklevel += n;
|
||||
if (c->c_stacklevel > c->c_maxstacklevel)
|
||||
c->c_maxstacklevel = c->c_stacklevel;
|
||||
}
|
||||
|
||||
static void
|
||||
com_pop(c, n)
|
||||
struct compiling *c;
|
||||
int n;
|
||||
{
|
||||
if (c->c_stacklevel < n) {
|
||||
fprintf(stderr,
|
||||
"%s:%d: underflow! nexti=%d, level=%d, n=%d\n",
|
||||
c->c_filename, c->c_lineno,
|
||||
c->c_nexti, c->c_stacklevel, n);
|
||||
c->c_stacklevel = 0;
|
||||
}
|
||||
else
|
||||
c->c_stacklevel -= n;
|
||||
}
|
||||
|
||||
static void
|
||||
com_done(c)
|
||||
struct compiling *c;
|
||||
|
@ -804,6 +838,7 @@ com_list_constructor(c, n)
|
|||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_node(c, CHILD(n, i));
|
||||
com_addoparg(c, BUILD_LIST, len);
|
||||
com_pop(c, len-1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -817,10 +852,12 @@ com_dictmaker(c, n)
|
|||
/* We must arrange things just right for STORE_SUBSCR.
|
||||
It wants the stack to look like (value) (dict) (key) */
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
com_node(c, CHILD(n, i+2)); /* value */
|
||||
com_addbyte(c, ROT_TWO);
|
||||
com_node(c, CHILD(n, i)); /* key */
|
||||
com_addbyte(c, STORE_SUBSCR);
|
||||
com_pop(c, 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,19 +873,24 @@ com_atom(c, n)
|
|||
ch = CHILD(n, 0);
|
||||
switch (TYPE(ch)) {
|
||||
case LPAR:
|
||||
if (TYPE(CHILD(n, 1)) == RPAR)
|
||||
if (TYPE(CHILD(n, 1)) == RPAR) {
|
||||
com_addoparg(c, BUILD_TUPLE, 0);
|
||||
com_push(c, 1);
|
||||
}
|
||||
else
|
||||
com_node(c, CHILD(n, 1));
|
||||
break;
|
||||
case LSQB:
|
||||
if (TYPE(CHILD(n, 1)) == RSQB)
|
||||
if (TYPE(CHILD(n, 1)) == RSQB) {
|
||||
com_addoparg(c, BUILD_LIST, 0);
|
||||
com_push(c, 1);
|
||||
}
|
||||
else
|
||||
com_list_constructor(c, CHILD(n, 1));
|
||||
break;
|
||||
case LBRACE: /* '{' [dictmaker] '}' */
|
||||
com_addoparg(c, BUILD_MAP, 0);
|
||||
com_push(c, 1);
|
||||
if (TYPE(CHILD(n, 1)) != RBRACE)
|
||||
com_dictmaker(c, CHILD(n, 1));
|
||||
break;
|
||||
|
@ -865,6 +907,7 @@ com_atom(c, n)
|
|||
DECREF(v);
|
||||
}
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
break;
|
||||
case STRING:
|
||||
v = parsestrplus(n);
|
||||
|
@ -877,12 +920,14 @@ com_atom(c, n)
|
|||
DECREF(v);
|
||||
}
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
break;
|
||||
case NAME:
|
||||
com_addopname(c, LOAD_NAME, ch);
|
||||
com_push(c, 1);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "node type %d\n", TYPE(ch));
|
||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(ch)); */
|
||||
com_error(c, SystemError, "com_atom: unexpected node type");
|
||||
}
|
||||
}
|
||||
|
@ -905,11 +950,13 @@ com_slice(c, n, op)
|
|||
com_node(c, CHILD(n, 1));
|
||||
com_addbyte(c, op+2);
|
||||
}
|
||||
com_pop(c, 1);
|
||||
}
|
||||
else {
|
||||
com_node(c, CHILD(n, 0));
|
||||
com_node(c, CHILD(n, 2));
|
||||
com_addbyte(c, op+3);
|
||||
com_pop(c, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -920,7 +967,7 @@ com_argument(c, n, pkeywords)
|
|||
object **pkeywords;
|
||||
{
|
||||
node *m;
|
||||
REQ(n, argument); /* [test '='] test; really [ keyword '='] keyword */
|
||||
REQ(n, argument); /* [test '='] test; really [keyword '='] test */
|
||||
if (NCH(n) == 1) {
|
||||
if (*pkeywords != NULL) {
|
||||
com_error(c, SyntaxError,
|
||||
|
@ -952,6 +999,7 @@ com_argument(c, n, pkeywords)
|
|||
if (dict2insert(*pkeywords, v, v) != 0)
|
||||
c->c_errors++;
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, v));
|
||||
com_push(c, 1);
|
||||
DECREF(v);
|
||||
}
|
||||
}
|
||||
|
@ -984,6 +1032,7 @@ com_call_function(c, n)
|
|||
com_error(c, SyntaxError, "more than 255 arguments");
|
||||
}
|
||||
com_addoparg(c, CALL_FUNCTION, na | (nk << 8));
|
||||
com_pop(c, na + 2*nk);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1007,6 +1056,7 @@ com_sliceobj(c, n)
|
|||
/* first argument */
|
||||
if (TYPE(CHILD(n,i)) == COLON) {
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
|
@ -1020,7 +1070,10 @@ com_sliceobj(c, n)
|
|||
com_node(c, CHILD(n,i));
|
||||
i++;
|
||||
}
|
||||
else com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
else {
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
}
|
||||
/* remaining arguments */
|
||||
for (; i < NCH(n); i++) {
|
||||
ns++;
|
||||
|
@ -1029,11 +1082,13 @@ com_sliceobj(c, n)
|
|||
if (NCH(ch) == 1) {
|
||||
/* right argument of ':' missing */
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
}
|
||||
else
|
||||
com_node(c, CHILD(ch,1));
|
||||
}
|
||||
com_addoparg(c, BUILD_SLICE, ns);
|
||||
com_pop(c, 1 + (ns == 3));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1045,8 +1100,10 @@ com_subscript(c, n)
|
|||
REQ(n, subscript);
|
||||
ch = CHILD(n,0);
|
||||
/* check for rubber index */
|
||||
if (TYPE(ch) == DOT && TYPE(CHILD(n,1)) == DOT)
|
||||
if (TYPE(ch) == DOT && TYPE(CHILD(n,1)) == DOT) {
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_Ellipsis));
|
||||
com_push(c, 1);
|
||||
}
|
||||
else {
|
||||
/* check for slice */
|
||||
if ((TYPE(ch) == COLON || NCH(n) > 1))
|
||||
|
@ -1070,15 +1127,20 @@ com_subscriptlist(c, n, assigning)
|
|||
if (NCH(n) == 1) {
|
||||
node *sub = CHILD(n, 0); /* subscript */
|
||||
/* Make it is a simple slice.
|
||||
should have exactly one colon. */
|
||||
Should have exactly one colon. */
|
||||
if ((TYPE(CHILD(sub, 0)) == COLON
|
||||
|| (NCH(sub) > 1 && TYPE(CHILD(sub, 1)) == COLON))
|
||||
&& (TYPE(CHILD(sub,NCH(sub)-1)) != sliceop)) {
|
||||
&& (TYPE(CHILD(sub,NCH(sub)-1)) != sliceop))
|
||||
{
|
||||
if (assigning == OP_APPLY)
|
||||
op = SLICE;
|
||||
else
|
||||
op = ((assigning == OP_ASSIGN) ? STORE_SLICE : DELETE_SLICE);
|
||||
com_slice(c, sub, op);
|
||||
if (op == STORE_SLICE)
|
||||
com_pop(c, 2);
|
||||
else if (op == DELETE_SLICE)
|
||||
com_pop(c, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1086,13 +1148,25 @@ com_subscriptlist(c, n, assigning)
|
|||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_subscript(c, CHILD(n, i));
|
||||
/* Put multiple subscripts into a tuple */
|
||||
if (NCH(n) > 1)
|
||||
com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 2);
|
||||
if (assigning == OP_APPLY)
|
||||
if (NCH(n) > 1) {
|
||||
i = (NCH(n)+1) / 2;
|
||||
com_addoparg(c, BUILD_TUPLE, i);
|
||||
com_pop(c, i-1);
|
||||
}
|
||||
if (assigning == OP_APPLY) {
|
||||
op = BINARY_SUBSCR;
|
||||
else
|
||||
op = ((assigning == OP_ASSIGN) ? STORE_SUBSCR : DELETE_SUBSCR);
|
||||
i = 1;
|
||||
}
|
||||
else if (assigning == OP_ASSIGN) {
|
||||
op = STORE_SUBSCR;
|
||||
i = 3;
|
||||
}
|
||||
else {
|
||||
op = DELETE_SUBSCR;
|
||||
i = 2;
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, i);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1129,6 +1203,7 @@ com_power(c, n)
|
|||
if (TYPE(CHILD(n, i)) == DOUBLESTAR) {
|
||||
com_factor(c, CHILD(n, i+1));
|
||||
com_addbyte(c, BINARY_POWER);
|
||||
com_pop(c, 1);
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -1186,6 +1261,7 @@ com_term(c, n)
|
|||
op = 255;
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1213,6 +1289,7 @@ com_arith_expr(c, n)
|
|||
op = 255;
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1240,6 +1317,7 @@ com_shift_expr(c, n)
|
|||
op = 255;
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1263,6 +1341,7 @@ com_and_expr(c, n)
|
|||
op = 255;
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1286,6 +1365,7 @@ com_xor_expr(c, n)
|
|||
op = 255;
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1309,6 +1389,7 @@ com_expr(c, n)
|
|||
op = 255;
|
||||
}
|
||||
com_addbyte(c, op);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1387,7 +1468,7 @@ com_comparison(c, n)
|
|||
L1: b, 0 ROT_TWO
|
||||
0, b POP_TOP
|
||||
0
|
||||
L2:
|
||||
L2: 0-or-1
|
||||
****************************************************************/
|
||||
|
||||
anchor = 0;
|
||||
|
@ -1396,6 +1477,7 @@ com_comparison(c, n)
|
|||
com_expr(c, CHILD(n, i));
|
||||
if (i+2 < NCH(n)) {
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
com_addbyte(c, ROT_THREE);
|
||||
}
|
||||
op = cmp_type(CHILD(n, i-1));
|
||||
|
@ -1404,9 +1486,11 @@ com_comparison(c, n)
|
|||
"com_comparison: unknown comparison op");
|
||||
}
|
||||
com_addoparg(c, COMPARE_OP, op);
|
||||
com_pop(c, 1);
|
||||
if (i+2 < NCH(n)) {
|
||||
com_addfwref(c, JUMP_IF_FALSE, &anchor);
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1451,6 +1535,7 @@ com_and_test(c, n)
|
|||
break;
|
||||
com_addfwref(c, JUMP_IF_FALSE, &anchor);
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
if (anchor)
|
||||
com_backpatch(c, anchor);
|
||||
|
@ -1461,7 +1546,7 @@ com_test(c, n)
|
|||
struct compiling *c;
|
||||
node *n;
|
||||
{
|
||||
REQ(n, test); /* and_test ('and' and_test)* | lambdef */
|
||||
REQ(n, test); /* and_test ('or' and_test)* | lambdef */
|
||||
if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
|
||||
object *v;
|
||||
int i;
|
||||
|
@ -1476,7 +1561,9 @@ com_test(c, n)
|
|||
DECREF(v);
|
||||
}
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
com_addoparg(c, MAKE_FUNCTION, ndefs);
|
||||
com_pop(c, ndefs);
|
||||
}
|
||||
else {
|
||||
int anchor = 0;
|
||||
|
@ -1487,6 +1574,7 @@ com_test(c, n)
|
|||
break;
|
||||
com_addfwref(c, JUMP_IF_TRUE, &anchor);
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
if (anchor)
|
||||
com_backpatch(c, anchor);
|
||||
|
@ -1510,6 +1598,7 @@ com_list(c, n, toplevel)
|
|||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_node(c, CHILD(n, i));
|
||||
com_addoparg(c, BUILD_TUPLE, len);
|
||||
com_pop(c, len-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1526,6 +1615,7 @@ com_assign_attr(c, n, assigning)
|
|||
int assigning;
|
||||
{
|
||||
com_addopname(c, assigning ? STORE_ATTR : DELETE_ATTR, n);
|
||||
com_pop(c, assigning ? 2 : 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1559,8 +1649,11 @@ com_assign_tuple(c, n, assigning)
|
|||
int i;
|
||||
if (TYPE(n) != testlist)
|
||||
REQ(n, exprlist);
|
||||
if (assigning)
|
||||
com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2);
|
||||
if (assigning) {
|
||||
i = (NCH(n)+1)/2;
|
||||
com_addoparg(c, UNPACK_TUPLE, i);
|
||||
com_push(c, i-1);
|
||||
}
|
||||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_assign(c, CHILD(n, i), assigning);
|
||||
}
|
||||
|
@ -1572,8 +1665,11 @@ com_assign_list(c, n, assigning)
|
|||
int assigning;
|
||||
{
|
||||
int i;
|
||||
if (assigning)
|
||||
com_addoparg(c, UNPACK_LIST, (NCH(n)+1)/2);
|
||||
if (assigning) {
|
||||
i = (NCH(n)+1)/2;
|
||||
com_addoparg(c, UNPACK_LIST, i);
|
||||
com_push(c, i-1);
|
||||
}
|
||||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_assign(c, CHILD(n, i), assigning);
|
||||
}
|
||||
|
@ -1586,6 +1682,8 @@ com_assign_name(c, n, assigning)
|
|||
{
|
||||
REQ(n, NAME);
|
||||
com_addopname(c, assigning ? STORE_NAME : DELETE_NAME, n);
|
||||
if (assigning)
|
||||
com_pop(c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1686,13 +1784,14 @@ com_assign(c, n, assigning)
|
|||
return;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "node type %d\n", TYPE(n));
|
||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(n)); */
|
||||
com_error(c, SystemError, "com_assign: bad node");
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Forward */ static node *get_rawdocstring PROTO((node *));
|
||||
|
||||
static void
|
||||
com_expr_stmt(c, n)
|
||||
|
@ -1700,18 +1799,24 @@ com_expr_stmt(c, n)
|
|||
node *n;
|
||||
{
|
||||
REQ(n, expr_stmt); /* testlist ('=' testlist)* */
|
||||
/* Forget it if we have just a doc string here */
|
||||
if (NCH(n) == 1 && get_rawdocstring(n) != NULL)
|
||||
return;
|
||||
com_node(c, CHILD(n, NCH(n)-1));
|
||||
if (NCH(n) == 1) {
|
||||
if (c->c_interactive)
|
||||
com_addbyte(c, PRINT_EXPR);
|
||||
else
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
for (i = 0; i < NCH(n)-2; i+=2) {
|
||||
if (i+2 < NCH(n)-2)
|
||||
if (i+2 < NCH(n)-2) {
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
}
|
||||
com_assign(c, CHILD(n, i), OP_ASSIGN);
|
||||
}
|
||||
}
|
||||
|
@ -1727,6 +1832,7 @@ com_print_stmt(c, n)
|
|||
for (i = 1; i < NCH(n); i += 2) {
|
||||
com_node(c, CHILD(n, i));
|
||||
com_addbyte(c, PRINT_ITEM);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
if (TYPE(CHILD(n, NCH(n)-1)) != COMMA)
|
||||
com_addbyte(c, PRINT_NEWLINE);
|
||||
|
@ -1742,11 +1848,14 @@ com_return_stmt(c, n)
|
|||
if (!c->c_infunction) {
|
||||
com_error(c, SyntaxError, "'return' outside function");
|
||||
}
|
||||
if (NCH(n) < 2)
|
||||
if (NCH(n) < 2) {
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
}
|
||||
else
|
||||
com_node(c, CHILD(n, 1));
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1754,6 +1863,7 @@ com_raise_stmt(c, n)
|
|||
struct compiling *c;
|
||||
node *n;
|
||||
{
|
||||
int i;
|
||||
REQ(n, raise_stmt); /* 'raise' test [',' test [',' test]] */
|
||||
com_node(c, CHILD(n, 1));
|
||||
if (NCH(n) > 3) {
|
||||
|
@ -1761,7 +1871,9 @@ com_raise_stmt(c, n)
|
|||
if (NCH(n) > 5)
|
||||
com_node(c, CHILD(n, 5));
|
||||
}
|
||||
com_addoparg(c, RAISE_VARARGS, NCH(n)/2);
|
||||
i = NCH(n)/2;
|
||||
com_addoparg(c, RAISE_VARARGS, i);
|
||||
com_pop(c, i);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1777,16 +1889,20 @@ com_import_stmt(c, n)
|
|||
/* 'from' dotted_name 'import' ... */
|
||||
REQ(CHILD(n, 1), dotted_name);
|
||||
com_addopname(c, IMPORT_NAME, CHILD(n, 1));
|
||||
com_push(c, 1);
|
||||
for (i = 3; i < NCH(n); i += 2)
|
||||
com_addopname(c, IMPORT_FROM, CHILD(n, i));
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
else {
|
||||
/* 'import' ... */
|
||||
for (i = 1; i < NCH(n); i += 2) {
|
||||
REQ(CHILD(n, i), dotted_name);
|
||||
com_addopname(c, IMPORT_NAME, CHILD(n, i));
|
||||
com_push(c, 1);
|
||||
com_addopname(c, STORE_NAME, CHILD(CHILD(n, i), 0));
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1868,9 +1984,10 @@ com_newlocal(c, name)
|
|||
return i;
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_OBSOLETE_ACCESS
|
||||
|
||||
#define strequ(a, b) (strcmp((a), (b)) == 0)
|
||||
|
||||
#ifdef SUPPORT_OBSOLETE_ACCESS
|
||||
static void
|
||||
com_access_stmt(c, n)
|
||||
struct compiling *c;
|
||||
|
@ -1939,13 +2056,18 @@ com_exec_stmt(c, n)
|
|||
com_node(c, CHILD(n, 1));
|
||||
if (NCH(n) >= 4)
|
||||
com_node(c, CHILD(n, 3));
|
||||
else
|
||||
else {
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
}
|
||||
if (NCH(n) >= 6)
|
||||
com_node(c, CHILD(n, 5));
|
||||
else
|
||||
else {
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
}
|
||||
com_addbyte(c, EXEC_STMT);
|
||||
com_pop(c, 3);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1965,9 +2087,11 @@ com_if_stmt(c, n)
|
|||
com_node(c, CHILD(n, i+1));
|
||||
com_addfwref(c, JUMP_IF_FALSE, &a);
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
com_node(c, CHILD(n, i+3));
|
||||
com_addfwref(c, JUMP_FORWARD, &anchor);
|
||||
com_backpatch(c, a);
|
||||
/* We jump here with an extra entry which we now pop */
|
||||
com_addbyte(c, POP_TOP);
|
||||
}
|
||||
if (i+2 < NCH(n))
|
||||
|
@ -1991,12 +2115,14 @@ com_while_stmt(c, n)
|
|||
com_node(c, CHILD(n, 1));
|
||||
com_addfwref(c, JUMP_IF_FALSE, &anchor);
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
c->c_loops++;
|
||||
com_node(c, CHILD(n, 3));
|
||||
c->c_loops--;
|
||||
com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
|
||||
c->c_begin = save_begin;
|
||||
com_backpatch(c, anchor);
|
||||
/* We jump here with one entry more on the stack */
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_addbyte(c, POP_BLOCK);
|
||||
block_pop(c, SETUP_LOOP);
|
||||
|
@ -2023,10 +2149,12 @@ com_for_stmt(c, n)
|
|||
if (v == NULL)
|
||||
c->c_errors++;
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, v));
|
||||
com_push(c, 1);
|
||||
XDECREF(v);
|
||||
c->c_begin = c->c_nexti;
|
||||
com_addoparg(c, SET_LINENO, n->n_lineno);
|
||||
com_addfwref(c, FOR_LOOP, &anchor);
|
||||
com_push(c, 1);
|
||||
com_assign(c, CHILD(n, 1), OP_ASSIGN);
|
||||
c->c_loops++;
|
||||
com_node(c, CHILD(n, 5));
|
||||
|
@ -2034,6 +2162,7 @@ com_for_stmt(c, n)
|
|||
com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
|
||||
c->c_begin = save_begin;
|
||||
com_backpatch(c, anchor);
|
||||
com_pop(c, 2); /* FOR_LOOP has popped these */
|
||||
com_addbyte(c, POP_BLOCK);
|
||||
block_pop(c, SETUP_LOOP);
|
||||
if (NCH(n) > 8)
|
||||
|
@ -2128,34 +2257,49 @@ com_try_except(c, n)
|
|||
for (i = 3;
|
||||
i < NCH(n) && TYPE(ch = CHILD(n, i)) == except_clause;
|
||||
i += 3) {
|
||||
/* except_clause: 'except' [expr [',' expr]] */
|
||||
/* except_clause: 'except' [expr [',' var]] */
|
||||
if (except_anchor == 0) {
|
||||
com_error(c, SyntaxError,
|
||||
"default 'except:' must be last");
|
||||
break;
|
||||
}
|
||||
except_anchor = 0;
|
||||
com_push(c, 3); /* tb, val, exc pushed by exception */
|
||||
com_addoparg(c, SET_LINENO, ch->n_lineno);
|
||||
if (NCH(ch) > 1) {
|
||||
com_addbyte(c, DUP_TOP);
|
||||
com_push(c, 1);
|
||||
com_node(c, CHILD(ch, 1));
|
||||
com_addoparg(c, COMPARE_OP, EXC_MATCH);
|
||||
com_pop(c, 1);
|
||||
com_addfwref(c, JUMP_IF_FALSE, &except_anchor);
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
if (NCH(ch) > 3)
|
||||
com_assign(c, CHILD(ch, 3), OP_ASSIGN);
|
||||
else
|
||||
else {
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
com_addbyte(c, POP_TOP);
|
||||
com_pop(c, 1);
|
||||
com_node(c, CHILD(n, i+2));
|
||||
com_addfwref(c, JUMP_FORWARD, &end_anchor);
|
||||
if (except_anchor) {
|
||||
com_backpatch(c, except_anchor);
|
||||
/* We come in with [tb, val, exc, 0] on the
|
||||
stack; one pop and it's the same as
|
||||
expected at the start of the loop */
|
||||
com_addbyte(c, POP_TOP);
|
||||
}
|
||||
}
|
||||
/* We actually come in here with [tb, val, exc] but the
|
||||
END_FINALLY will zap those and jump around.
|
||||
The c_stacklevel does not reflect them so we need not pop
|
||||
anything. */
|
||||
com_addbyte(c, END_FINALLY);
|
||||
com_backpatch(c, else_anchor);
|
||||
if (i < NCH(n))
|
||||
|
@ -2178,12 +2322,18 @@ com_try_finally(c, n)
|
|||
block_pop(c, SETUP_FINALLY);
|
||||
block_push(c, END_FINALLY);
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
/* While the generated code pushes only one item,
|
||||
the try-finally handling can enter here with
|
||||
up to three items. OK, here are the details:
|
||||
3 for an exception, 2 for RETURN, 1 for BREAK. */
|
||||
com_push(c, 3);
|
||||
com_backpatch(c, finally_anchor);
|
||||
ch = CHILD(n, NCH(n)-1);
|
||||
com_addoparg(c, SET_LINENO, ch->n_lineno);
|
||||
com_node(c, ch);
|
||||
com_addbyte(c, END_FINALLY);
|
||||
block_pop(c, END_FINALLY);
|
||||
com_pop(c, 3); /* Matches the com_push above */
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2200,38 +2350,37 @@ com_try_stmt(c, n)
|
|||
com_try_except(c, n);
|
||||
}
|
||||
|
||||
static object *
|
||||
get_docstring(n)
|
||||
static node *
|
||||
get_rawdocstring(n)
|
||||
node *n;
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Label to avoid tail recursion */
|
||||
next:
|
||||
switch (TYPE(n)) {
|
||||
|
||||
case suite:
|
||||
if (NCH(n) == 1)
|
||||
return get_docstring(CHILD(n, 0));
|
||||
else {
|
||||
for (i = 0; i < NCH(n); i++) {
|
||||
node *ch = CHILD(n, i);
|
||||
if (TYPE(ch) == stmt)
|
||||
return get_docstring(ch);
|
||||
if (NCH(n) == 1) {
|
||||
n = CHILD(n, 0);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Fall through */
|
||||
case file_input:
|
||||
for (i = 0; i < NCH(n); i++) {
|
||||
node *ch = CHILD(n, i);
|
||||
if (TYPE(ch) == stmt)
|
||||
return get_docstring(ch);
|
||||
if (TYPE(ch) == stmt) {
|
||||
n = ch;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case stmt:
|
||||
case simple_stmt:
|
||||
case small_stmt:
|
||||
return get_docstring(CHILD(n, 0));
|
||||
n = CHILD(n, 0);
|
||||
goto next;
|
||||
|
||||
case expr_stmt:
|
||||
case testlist:
|
||||
|
@ -2247,19 +2396,31 @@ get_docstring(n)
|
|||
case term:
|
||||
case factor:
|
||||
case power:
|
||||
if (NCH(n) == 1)
|
||||
return get_docstring(CHILD(n, 0));
|
||||
if (NCH(n) == 1) {
|
||||
n = CHILD(n, 0);
|
||||
goto next;
|
||||
}
|
||||
break;
|
||||
|
||||
case atom:
|
||||
if (TYPE(CHILD(n, 0)) == STRING)
|
||||
return parsestrplus(n);
|
||||
return n;
|
||||
break;
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static object *
|
||||
get_docstring(n)
|
||||
node *n;
|
||||
{
|
||||
n = get_rawdocstring(n);
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
return parsestrplus(n);
|
||||
}
|
||||
|
||||
static void
|
||||
com_suite(c, n)
|
||||
struct compiling *c;
|
||||
|
@ -2345,6 +2506,7 @@ com_argdefs(c, n)
|
|||
if (ndefs) {
|
||||
com_addoparg(c, LOAD_CONST,
|
||||
com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
ndefs++;
|
||||
}
|
||||
}
|
||||
|
@ -2368,8 +2530,11 @@ com_funcdef(c, n)
|
|||
int i = com_addconst(c, v);
|
||||
int ndefs = com_argdefs(c, n);
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
com_addoparg(c, MAKE_FUNCTION, ndefs);
|
||||
com_pop(c, ndefs);
|
||||
com_addopname(c, STORE_NAME, CHILD(n, 1));
|
||||
com_pop(c, 1);
|
||||
DECREF(v);
|
||||
}
|
||||
}
|
||||
|
@ -2384,7 +2549,9 @@ com_bases(c, n)
|
|||
/* testlist: test (',' test)* [','] */
|
||||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_node(c, CHILD(n, i));
|
||||
com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 2);
|
||||
i = (NCH(n)+1) / 2;
|
||||
com_addoparg(c, BUILD_TUPLE, i);
|
||||
com_pop(c, i-1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2403,10 +2570,13 @@ com_classdef(c, n)
|
|||
/* Push the class name on the stack */
|
||||
i = com_addconst(c, v);
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
DECREF(v);
|
||||
/* Push the tuple of base classes on the stack */
|
||||
if (TYPE(CHILD(n, 2)) != LPAR)
|
||||
if (TYPE(CHILD(n, 2)) != LPAR) {
|
||||
com_addoparg(c, BUILD_TUPLE, 0);
|
||||
com_push(c, 1);
|
||||
}
|
||||
else
|
||||
com_bases(c, CHILD(n, 3));
|
||||
v = (object *)icompile(n, c);
|
||||
|
@ -2415,9 +2585,11 @@ com_classdef(c, n)
|
|||
else {
|
||||
i = com_addconst(c, v);
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
com_addoparg(c, MAKE_FUNCTION, 0);
|
||||
com_addoparg(c, CALL_FUNCTION, 0);
|
||||
com_addbyte(c, BUILD_CLASS);
|
||||
com_pop(c, 2);
|
||||
com_addopname(c, STORE_NAME, CHILD(n, 1));
|
||||
DECREF(v);
|
||||
}
|
||||
|
@ -2569,7 +2741,7 @@ com_node(c, n)
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "node type %d\n", TYPE(n));
|
||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(n)); */
|
||||
com_error(c, SystemError, "com_node: unexpected node type");
|
||||
}
|
||||
}
|
||||
|
@ -2584,8 +2756,10 @@ com_fpdef(c, n)
|
|||
REQ(n, fpdef); /* fpdef: NAME | '(' fplist ')' */
|
||||
if (TYPE(CHILD(n, 0)) == LPAR)
|
||||
com_fplist(c, CHILD(n, 1));
|
||||
else
|
||||
else {
|
||||
com_addoparg(c, STORE_FAST, com_newlocal(c, STR(CHILD(n, 0))));
|
||||
com_pop(c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2598,8 +2772,9 @@ com_fplist(c, n)
|
|||
com_fpdef(c, CHILD(n, 0));
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
com_addoparg(c, UNPACK_TUPLE, (NCH(n)+1)/2);
|
||||
int i = (NCH(n)+1)/2;
|
||||
com_addoparg(c, UNPACK_TUPLE, i);
|
||||
com_push(c, i-1);
|
||||
for (i = 0; i < NCH(n); i += 2)
|
||||
com_fpdef(c, CHILD(n, i));
|
||||
}
|
||||
|
@ -2684,6 +2859,7 @@ com_arglist(c, n)
|
|||
fp = CHILD(ch, 0);
|
||||
if (TYPE(fp) != NAME) {
|
||||
com_addoparg(c, LOAD_FAST, ilocal);
|
||||
com_push(c, 1);
|
||||
com_fpdef(c, ch);
|
||||
}
|
||||
ilocal++;
|
||||
|
@ -2711,7 +2887,9 @@ com_file_input(c, n)
|
|||
int i = com_addconst(c, doc);
|
||||
DECREF(doc);
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
com_addopnamestr(c, STORE_NAME, "__doc__");
|
||||
com_pop(c, 1);
|
||||
}
|
||||
for (i = 0; i < NCH(n); i++) {
|
||||
node *ch = CHILD(n, i);
|
||||
|
@ -2746,7 +2924,9 @@ compile_funcdef(c, n)
|
|||
com_node(c, CHILD(n, 4));
|
||||
c->c_infunction = 0;
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2768,6 +2948,7 @@ compile_lambdef(c, n)
|
|||
ch = CHILD(n, 2);
|
||||
com_node(c, ch);
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2789,13 +2970,17 @@ compile_classdef(c, n)
|
|||
int i = com_addconst(c, doc);
|
||||
DECREF(doc);
|
||||
com_addoparg(c, LOAD_CONST, i);
|
||||
com_push(c, 1);
|
||||
com_addopnamestr(c, STORE_NAME, "__doc__");
|
||||
com_pop(c, 1);
|
||||
}
|
||||
else
|
||||
(void) com_addconst(c, None);
|
||||
com_node(c, ch);
|
||||
com_addbyte(c, LOAD_LOCALS);
|
||||
com_push(c, 1);
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
com_pop(c, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2814,19 +2999,24 @@ compile_node(c, n)
|
|||
if (TYPE(n) != NEWLINE)
|
||||
com_node(c, n);
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
com_pop(c, 1);
|
||||
c->c_interactive--;
|
||||
break;
|
||||
|
||||
case file_input: /* A whole file, or built-in function exec() */
|
||||
com_file_input(c, n);
|
||||
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
|
||||
com_push(c, 1);
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
com_pop(c, 1);
|
||||
break;
|
||||
|
||||
case eval_input: /* Built-in function input() */
|
||||
com_node(c, CHILD(n, 0));
|
||||
com_addbyte(c, RETURN_VALUE);
|
||||
com_pop(c, 1);
|
||||
break;
|
||||
|
||||
case lambdef: /* anonymous function definition */
|
||||
|
@ -2842,7 +3032,7 @@ compile_node(c, n)
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "node type %d\n", TYPE(n));
|
||||
/* XXX fprintf(stderr, "node type %d\n", TYPE(n)); */
|
||||
com_error(c, SystemError,
|
||||
"compile_node: unexpected node type");
|
||||
}
|
||||
|
@ -3001,6 +3191,7 @@ jcompile(n, filename, base)
|
|||
if (!err_occurred())
|
||||
co = newcodeobject(sc.c_argcount,
|
||||
sc.c_nlocals,
|
||||
sc.c_maxstacklevel,
|
||||
sc.c_flags,
|
||||
sc.c_code,
|
||||
consts,
|
||||
|
|
Loading…
Reference in New Issue