New syntax: semicolons, continue statement.

For the latter we must keep track of the current block's type.
(We can't continue through a try statement, sigh.()
This commit is contained in:
Guido van Rossum 1991-07-27 21:34:52 +00:00
parent 76a00af3f2
commit 4bad92cc8a
1 changed files with 123 additions and 21 deletions

View File

@ -129,6 +129,9 @@ newcodeobject(code, consts, names, filename)
/* 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 */
@ -137,10 +140,45 @@ struct compiling {
int c_errors; /* counts errors occurred */
int c_infunction; /* set when compiling a function */
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_nblocks; /* current block stack level */
char *c_filename; /* filename of current node */
};
/* Interface to the block stack */
static void
block_push(c, type)
struct compiling *c;
int type;
{
if (c->c_nblocks >= MAXBLOCKS) {
err_setstr(TypeError, "too many statically nested blocks");
c->c_errors++;
}
else {
c->c_block[c->c_nblocks++] = type;
}
}
static void
block_pop(c, type)
struct compiling *c;
int type;
{
if (c->c_nblocks > 0)
c->c_nblocks--;
if (c->c_block[c->c_nblocks] != type && c->c_errors == 0) {
err_setstr(SystemError, "bad block pop");
c->c_errors++;
}
}
/* Prototypes */
static int com_init PROTO((struct compiling *, char *));
static void com_free PROTO((struct compiling *));
static void com_done PROTO((struct compiling *));
@ -170,6 +208,8 @@ com_init(c, filename)
c->c_errors = 0;
c->c_infunction = 0;
c->c_loops = 0;
c->c_begin = 0;
c->c_nblocks = 0;
c->c_filename = filename;
return 1;
@ -462,6 +502,24 @@ com_list_constructor(c, n)
com_addoparg(c, BUILD_LIST, len);
}
static void
com_dictmaker(c, n)
struct compiling *c;
node *n;
{
int i;
/* dictmaker: test ':' test (',' test ':' value)* [','] */
for (i = 0; i+2 < NCH(n); i += 4) {
/* 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_node(c, CHILD(n, i+2)); /* value */
com_addbyte(c, ROT_TWO);
com_node(c, CHILD(n, i)); /* key */
com_addbyte(c, STORE_SUBSCR);
}
}
static void
com_atom(c, n)
struct compiling *c;
@ -485,8 +543,10 @@ com_atom(c, n)
else
com_list_constructor(c, CHILD(n, 1));
break;
case LBRACE:
case LBRACE: /* '{' [dictmaker] '}' */
com_addoparg(c, BUILD_MAP, 0);
if (TYPE(CHILD(n, 1)) != RBRACE)
com_dictmaker(c, CHILD(n, 1));
break;
case BACKQUOTE:
com_node(c, CHILD(n, 1));
@ -1111,15 +1171,15 @@ com_expr_stmt(c, n)
struct compiling *c;
node *n;
{
REQ(n, expr_stmt); /* exprlist ('=' exprlist)* NEWLINE */
com_node(c, CHILD(n, NCH(n)-2));
if (NCH(n) == 2) {
REQ(n, expr_stmt); /* exprlist ('=' exprlist)* */
com_node(c, CHILD(n, NCH(n)-1));
if (NCH(n) == 1) {
com_addbyte(c, PRINT_EXPR);
}
else {
int i;
for (i = 0; i < NCH(n)-3; i+=2) {
if (i+2 < NCH(n)-3)
for (i = 0; i < NCH(n)-2; i+=2) {
if (i+2 < NCH(n)-2)
com_addbyte(c, DUP_TOP);
com_assign(c, CHILD(n, i), 1/*assign*/);
}
@ -1132,12 +1192,12 @@ com_print_stmt(c, n)
node *n;
{
int i;
REQ(n, print_stmt); /* 'print' (test ',')* [test] NEWLINE */
for (i = 1; i+1 < NCH(n); i += 2) {
REQ(n, print_stmt); /* 'print' (test ',')* [test] */
for (i = 1; i < NCH(n); i += 2) {
com_node(c, CHILD(n, i));
com_addbyte(c, PRINT_ITEM);
}
if (TYPE(CHILD(n, NCH(n)-2)) != COMMA)
if (TYPE(CHILD(n, NCH(n)-1)) != COMMA)
com_addbyte(c, PRINT_NEWLINE);
/* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */
}
@ -1147,12 +1207,12 @@ com_return_stmt(c, n)
struct compiling *c;
node *n;
{
REQ(n, return_stmt); /* 'return' [testlist] NEWLINE */
REQ(n, return_stmt); /* 'return' [testlist] */
if (!c->c_infunction) {
err_setstr(TypeError, "'return' outside function");
c->c_errors++;
}
if (NCH(n) == 2)
if (NCH(n) < 2)
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
else
com_node(c, CHILD(n, 1));
@ -1164,7 +1224,7 @@ com_raise_stmt(c, n)
struct compiling *c;
node *n;
{
REQ(n, raise_stmt); /* 'raise' expr [',' expr] NEWLINE */
REQ(n, raise_stmt); /* 'raise' test [',' test] */
com_node(c, CHILD(n, 1));
if (NCH(n) > 3)
com_node(c, CHILD(n, 3));
@ -1180,8 +1240,8 @@ com_import_stmt(c, n)
{
int i;
REQ(n, import_stmt);
/* 'import' NAME (',' NAME)* NEWLINE |
'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE */
/* 'import' NAME (',' NAME)* |
'from' NAME 'import' ('*' | NAME (',' NAME)*) */
if (STR(CHILD(n, 0))[0] == 'f') {
/* 'from' NAME 'import' ... */
REQ(CHILD(n, 1), NAME);
@ -1233,10 +1293,11 @@ com_while_stmt(c, n)
{
int break_anchor = 0;
int anchor = 0;
int begin;
int save_begin = c->c_begin;
REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
com_addfwref(c, SETUP_LOOP, &break_anchor);
begin = c->c_nexti;
block_push(c, SETUP_LOOP);
c->c_begin = c->c_nexti;
com_addoparg(c, SET_LINENO, n->n_lineno);
com_node(c, CHILD(n, 1));
com_addfwref(c, JUMP_IF_FALSE, &anchor);
@ -1244,10 +1305,12 @@ com_while_stmt(c, n)
c->c_loops++;
com_node(c, CHILD(n, 3));
c->c_loops--;
com_addoparg(c, JUMP_ABSOLUTE, begin);
com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
c->c_begin = save_begin;
com_backpatch(c, anchor);
com_addbyte(c, POP_TOP);
com_addbyte(c, POP_BLOCK);
block_pop(c, SETUP_LOOP);
if (NCH(n) > 4)
com_node(c, CHILD(n, 6));
com_backpatch(c, break_anchor);
@ -1261,26 +1324,29 @@ com_for_stmt(c, n)
object *v;
int break_anchor = 0;
int anchor = 0;
int begin;
int save_begin = c->c_begin;
REQ(n, for_stmt);
/* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */
com_addfwref(c, SETUP_LOOP, &break_anchor);
block_push(c, SETUP_LOOP);
com_node(c, CHILD(n, 3));
v = newintobject(0L);
if (v == NULL)
c->c_errors++;
com_addoparg(c, LOAD_CONST, com_addconst(c, v));
XDECREF(v);
begin = c->c_nexti;
c->c_begin = c->c_nexti;
com_addoparg(c, SET_LINENO, n->n_lineno);
com_addfwref(c, FOR_LOOP, &anchor);
com_assign(c, CHILD(n, 1), 1/*assigning*/);
c->c_loops++;
com_node(c, CHILD(n, 5));
c->c_loops--;
com_addoparg(c, JUMP_ABSOLUTE, begin);
com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
c->c_begin = save_begin;
com_backpatch(c, anchor);
com_addbyte(c, POP_BLOCK);
block_pop(c, SETUP_LOOP);
if (NCH(n) > 8)
com_node(c, CHILD(n, 8));
com_backpatch(c, break_anchor);
@ -1383,10 +1449,12 @@ com_try_stmt(c, n)
if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) {
/* Have a 'finally' clause */
com_addfwref(c, SETUP_FINALLY, &finally_anchor);
block_push(c, SETUP_FINALLY);
}
if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == except_clause) {
/* Have an 'except' clause */
com_addfwref(c, SETUP_EXCEPT, &except_anchor);
block_push(c, SETUP_EXCEPT);
}
com_node(c, CHILD(n, 2));
if (except_anchor) {
@ -1394,6 +1462,7 @@ com_try_stmt(c, n)
int i;
node *ch;
com_addbyte(c, POP_BLOCK);
block_pop(c, SETUP_EXCEPT);
com_addfwref(c, JUMP_FORWARD, &end_anchor);
com_backpatch(c, except_anchor);
for (i = 3;
@ -1434,12 +1503,15 @@ com_try_stmt(c, n)
if (finally_anchor) {
node *ch;
com_addbyte(c, POP_BLOCK);
block_pop(c, SETUP_FINALLY);
block_push(c, END_FINALLY);
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
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);
}
}
@ -1463,6 +1535,23 @@ com_suite(c, n)
}
}
static void
com_continue_stmt(c, n)
struct compiling *c;
node *n;
{
int i = c->c_nblocks;
if (i-- > 0 && c->c_block[i] == SETUP_LOOP) {
com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
}
else {
err_setstr(TypeError, "'continue' not properly in loop");
c->c_errors++;
}
/* XXX Could allow it inside a 'finally' clause
XXX if we could pop the exception still on the stack */
}
static void
com_funcdef(c, n)
struct compiling *c;
@ -1547,11 +1636,21 @@ com_node(c, n)
/* Trivial parse tree nodes */
case stmt:
case small_stmt:
case flow_stmt:
com_node(c, CHILD(n, 0));
break;
case simple_stmt:
/* small_stmt (';' small_stmt)* [';'] NEWLINE */
com_addoparg(c, SET_LINENO, n->n_lineno);
{
int i;
for (i = 0; i < NCH(n)-1; i += 2)
com_node(c, CHILD(n, i));
}
break;
case compound_stmt:
com_addoparg(c, SET_LINENO, n->n_lineno);
com_node(c, CHILD(n, 0));
@ -1565,7 +1664,7 @@ com_node(c, n)
case print_stmt:
com_print_stmt(c, n);
break;
case del_stmt: /* 'del' exprlist NEWLINE */
case del_stmt: /* 'del' exprlist */
com_assign(c, CHILD(n, 1), 0/*delete*/);
break;
case pass_stmt:
@ -1577,6 +1676,9 @@ com_node(c, n)
}
com_addbyte(c, BREAK_LOOP);
break;
case continue_stmt:
com_continue_stmt(c, n);
break;
case return_stmt:
com_return_stmt(c, n);
break;