Commit 4bad92cc authored by Guido van Rossum's avatar Guido van Rossum

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.()
parent 76a00af3
...@@ -129,6 +129,9 @@ newcodeobject(code, consts, names, filename) ...@@ -129,6 +129,9 @@ newcodeobject(code, consts, names, filename)
/* Data structure used internally */ /* Data structure used internally */
#define MAXBLOCKS 20 /* Max static block nesting within a function */
struct compiling { struct compiling {
object *c_code; /* string */ object *c_code; /* string */
object *c_consts; /* list of objects */ object *c_consts; /* list of objects */
...@@ -137,10 +140,45 @@ struct compiling { ...@@ -137,10 +140,45 @@ struct compiling {
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 */
int c_loops; /* counts nested loops */ 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 */ 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 */ /* Prototypes */
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 *));
static void com_done PROTO((struct compiling *)); static void com_done PROTO((struct compiling *));
...@@ -170,6 +208,8 @@ com_init(c, filename) ...@@ -170,6 +208,8 @@ com_init(c, filename)
c->c_errors = 0; c->c_errors = 0;
c->c_infunction = 0; c->c_infunction = 0;
c->c_loops = 0; c->c_loops = 0;
c->c_begin = 0;
c->c_nblocks = 0;
c->c_filename = filename; c->c_filename = filename;
return 1; return 1;
...@@ -462,6 +502,24 @@ com_list_constructor(c, n) ...@@ -462,6 +502,24 @@ com_list_constructor(c, n)
com_addoparg(c, BUILD_LIST, len); 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 static void
com_atom(c, n) com_atom(c, n)
struct compiling *c; struct compiling *c;
...@@ -485,8 +543,10 @@ com_atom(c, n) ...@@ -485,8 +543,10 @@ com_atom(c, n)
else else
com_list_constructor(c, CHILD(n, 1)); com_list_constructor(c, CHILD(n, 1));
break; break;
case LBRACE: case LBRACE: /* '{' [dictmaker] '}' */
com_addoparg(c, BUILD_MAP, 0); com_addoparg(c, BUILD_MAP, 0);
if (TYPE(CHILD(n, 1)) != RBRACE)
com_dictmaker(c, CHILD(n, 1));
break; break;
case BACKQUOTE: case BACKQUOTE:
com_node(c, CHILD(n, 1)); com_node(c, CHILD(n, 1));
...@@ -1111,15 +1171,15 @@ com_expr_stmt(c, n) ...@@ -1111,15 +1171,15 @@ com_expr_stmt(c, n)
struct compiling *c; struct compiling *c;
node *n; node *n;
{ {
REQ(n, expr_stmt); /* exprlist ('=' exprlist)* NEWLINE */ REQ(n, expr_stmt); /* exprlist ('=' exprlist)* */
com_node(c, CHILD(n, NCH(n)-2)); com_node(c, CHILD(n, NCH(n)-1));
if (NCH(n) == 2) { if (NCH(n) == 1) {
com_addbyte(c, PRINT_EXPR); com_addbyte(c, PRINT_EXPR);
} }
else { else {
int i; int i;
for (i = 0; i < NCH(n)-3; i+=2) { for (i = 0; i < NCH(n)-2; i+=2) {
if (i+2 < NCH(n)-3) if (i+2 < NCH(n)-2)
com_addbyte(c, DUP_TOP); com_addbyte(c, DUP_TOP);
com_assign(c, CHILD(n, i), 1/*assign*/); com_assign(c, CHILD(n, i), 1/*assign*/);
} }
...@@ -1132,12 +1192,12 @@ com_print_stmt(c, n) ...@@ -1132,12 +1192,12 @@ com_print_stmt(c, n)
node *n; node *n;
{ {
int i; int i;
REQ(n, print_stmt); /* 'print' (test ',')* [test] NEWLINE */ REQ(n, print_stmt); /* 'print' (test ',')* [test] */
for (i = 1; i+1 < NCH(n); i += 2) { for (i = 1; i < NCH(n); i += 2) {
com_node(c, CHILD(n, i)); com_node(c, CHILD(n, i));
com_addbyte(c, PRINT_ITEM); 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); com_addbyte(c, PRINT_NEWLINE);
/* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */ /* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */
} }
...@@ -1147,12 +1207,12 @@ com_return_stmt(c, n) ...@@ -1147,12 +1207,12 @@ com_return_stmt(c, n)
struct compiling *c; struct compiling *c;
node *n; node *n;
{ {
REQ(n, return_stmt); /* 'return' [testlist] NEWLINE */ REQ(n, return_stmt); /* 'return' [testlist] */
if (!c->c_infunction) { if (!c->c_infunction) {
err_setstr(TypeError, "'return' outside function"); err_setstr(TypeError, "'return' outside function");
c->c_errors++; c->c_errors++;
} }
if (NCH(n) == 2) if (NCH(n) < 2)
com_addoparg(c, LOAD_CONST, com_addconst(c, None)); com_addoparg(c, LOAD_CONST, com_addconst(c, None));
else else
com_node(c, CHILD(n, 1)); com_node(c, CHILD(n, 1));
...@@ -1164,7 +1224,7 @@ com_raise_stmt(c, n) ...@@ -1164,7 +1224,7 @@ com_raise_stmt(c, n)
struct compiling *c; struct compiling *c;
node *n; node *n;
{ {
REQ(n, raise_stmt); /* 'raise' expr [',' expr] NEWLINE */ REQ(n, raise_stmt); /* 'raise' 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));
...@@ -1180,8 +1240,8 @@ com_import_stmt(c, n) ...@@ -1180,8 +1240,8 @@ com_import_stmt(c, n)
{ {
int i; int i;
REQ(n, import_stmt); REQ(n, import_stmt);
/* 'import' NAME (',' NAME)* NEWLINE | /* 'import' NAME (',' NAME)* |
'from' NAME 'import' ('*' | NAME (',' NAME)*) NEWLINE */ 'from' NAME 'import' ('*' | NAME (',' NAME)*) */
if (STR(CHILD(n, 0))[0] == 'f') { if (STR(CHILD(n, 0))[0] == 'f') {
/* 'from' NAME 'import' ... */ /* 'from' NAME 'import' ... */
REQ(CHILD(n, 1), NAME); REQ(CHILD(n, 1), NAME);
...@@ -1233,10 +1293,11 @@ com_while_stmt(c, n) ...@@ -1233,10 +1293,11 @@ com_while_stmt(c, n)
{ {
int break_anchor = 0; int break_anchor = 0;
int anchor = 0; int anchor = 0;
int begin; int save_begin = c->c_begin;
REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */ REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
com_addfwref(c, SETUP_LOOP, &break_anchor); 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_addoparg(c, SET_LINENO, n->n_lineno);
com_node(c, CHILD(n, 1)); com_node(c, CHILD(n, 1));
com_addfwref(c, JUMP_IF_FALSE, &anchor); com_addfwref(c, JUMP_IF_FALSE, &anchor);
...@@ -1244,10 +1305,12 @@ com_while_stmt(c, n) ...@@ -1244,10 +1305,12 @@ com_while_stmt(c, n)
c->c_loops++; c->c_loops++;
com_node(c, CHILD(n, 3)); com_node(c, CHILD(n, 3));
c->c_loops--; 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_backpatch(c, anchor);
com_addbyte(c, POP_TOP); com_addbyte(c, POP_TOP);
com_addbyte(c, POP_BLOCK); com_addbyte(c, POP_BLOCK);
block_pop(c, SETUP_LOOP);
if (NCH(n) > 4) if (NCH(n) > 4)
com_node(c, CHILD(n, 6)); com_node(c, CHILD(n, 6));
com_backpatch(c, break_anchor); com_backpatch(c, break_anchor);
...@@ -1261,26 +1324,29 @@ com_for_stmt(c, n) ...@@ -1261,26 +1324,29 @@ com_for_stmt(c, n)
object *v; object *v;
int break_anchor = 0; int break_anchor = 0;
int anchor = 0; int anchor = 0;
int begin; int save_begin = c->c_begin;
REQ(n, for_stmt); REQ(n, for_stmt);
/* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */ /* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */
com_addfwref(c, SETUP_LOOP, &break_anchor); com_addfwref(c, SETUP_LOOP, &break_anchor);
block_push(c, SETUP_LOOP);
com_node(c, CHILD(n, 3)); com_node(c, CHILD(n, 3));
v = newintobject(0L); v = newintobject(0L);
if (v == NULL) if (v == NULL)
c->c_errors++; c->c_errors++;
com_addoparg(c, LOAD_CONST, com_addconst(c, v)); com_addoparg(c, LOAD_CONST, com_addconst(c, v));
XDECREF(v); XDECREF(v);
begin = c->c_nexti; c->c_begin = c->c_nexti;
com_addoparg(c, SET_LINENO, n->n_lineno); com_addoparg(c, SET_LINENO, n->n_lineno);
com_addfwref(c, FOR_LOOP, &anchor); com_addfwref(c, FOR_LOOP, &anchor);
com_assign(c, CHILD(n, 1), 1/*assigning*/); com_assign(c, CHILD(n, 1), 1/*assigning*/);
c->c_loops++; c->c_loops++;
com_node(c, CHILD(n, 5)); com_node(c, CHILD(n, 5));
c->c_loops--; 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_backpatch(c, anchor);
com_addbyte(c, POP_BLOCK); com_addbyte(c, POP_BLOCK);
block_pop(c, SETUP_LOOP);
if (NCH(n) > 8) if (NCH(n) > 8)
com_node(c, CHILD(n, 8)); com_node(c, CHILD(n, 8));
com_backpatch(c, break_anchor); com_backpatch(c, break_anchor);
...@@ -1383,10 +1449,12 @@ com_try_stmt(c, n) ...@@ -1383,10 +1449,12 @@ com_try_stmt(c, n)
if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) { if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) {
/* Have a 'finally' clause */ /* Have a 'finally' clause */
com_addfwref(c, SETUP_FINALLY, &finally_anchor); com_addfwref(c, SETUP_FINALLY, &finally_anchor);
block_push(c, SETUP_FINALLY);
} }
if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == except_clause) { if (NCH(n) > 3 && TYPE(CHILD(n, 3)) == except_clause) {
/* Have an 'except' clause */ /* Have an 'except' clause */
com_addfwref(c, SETUP_EXCEPT, &except_anchor); com_addfwref(c, SETUP_EXCEPT, &except_anchor);
block_push(c, SETUP_EXCEPT);
} }
com_node(c, CHILD(n, 2)); com_node(c, CHILD(n, 2));
if (except_anchor) { if (except_anchor) {
...@@ -1394,6 +1462,7 @@ com_try_stmt(c, n) ...@@ -1394,6 +1462,7 @@ com_try_stmt(c, n)
int i; int i;
node *ch; node *ch;
com_addbyte(c, POP_BLOCK); com_addbyte(c, POP_BLOCK);
block_pop(c, SETUP_EXCEPT);
com_addfwref(c, JUMP_FORWARD, &end_anchor); com_addfwref(c, JUMP_FORWARD, &end_anchor);
com_backpatch(c, except_anchor); com_backpatch(c, except_anchor);
for (i = 3; for (i = 3;
...@@ -1434,12 +1503,15 @@ com_try_stmt(c, n) ...@@ -1434,12 +1503,15 @@ com_try_stmt(c, n)
if (finally_anchor) { if (finally_anchor) {
node *ch; node *ch;
com_addbyte(c, POP_BLOCK); 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_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_backpatch(c, finally_anchor); com_backpatch(c, finally_anchor);
ch = CHILD(n, NCH(n)-1); ch = CHILD(n, NCH(n)-1);
com_addoparg(c, SET_LINENO, ch->n_lineno); com_addoparg(c, SET_LINENO, ch->n_lineno);
com_node(c, ch); com_node(c, ch);
com_addbyte(c, END_FINALLY); com_addbyte(c, END_FINALLY);
block_pop(c, END_FINALLY);
} }
} }
...@@ -1463,6 +1535,23 @@ com_suite(c, n) ...@@ -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 static void
com_funcdef(c, n) com_funcdef(c, n)
struct compiling *c; struct compiling *c;
...@@ -1547,11 +1636,21 @@ com_node(c, n) ...@@ -1547,11 +1636,21 @@ com_node(c, n)
/* Trivial parse tree nodes */ /* Trivial parse tree nodes */
case stmt: case stmt:
case small_stmt:
case flow_stmt: case flow_stmt:
com_node(c, CHILD(n, 0)); com_node(c, CHILD(n, 0));
break; break;
case simple_stmt: 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: case compound_stmt:
com_addoparg(c, SET_LINENO, n->n_lineno); com_addoparg(c, SET_LINENO, n->n_lineno);
com_node(c, CHILD(n, 0)); com_node(c, CHILD(n, 0));
...@@ -1565,7 +1664,7 @@ com_node(c, n) ...@@ -1565,7 +1664,7 @@ com_node(c, n)
case print_stmt: case print_stmt:
com_print_stmt(c, n); com_print_stmt(c, n);
break; break;
case del_stmt: /* 'del' exprlist NEWLINE */ case del_stmt: /* 'del' exprlist */
com_assign(c, CHILD(n, 1), 0/*delete*/); com_assign(c, CHILD(n, 1), 0/*delete*/);
break; break;
case pass_stmt: case pass_stmt:
...@@ -1577,6 +1676,9 @@ com_node(c, n) ...@@ -1577,6 +1676,9 @@ com_node(c, n)
} }
com_addbyte(c, BREAK_LOOP); com_addbyte(c, BREAK_LOOP);
break; break;
case continue_stmt:
com_continue_stmt(c, n);
break;
case return_stmt: case return_stmt:
com_return_stmt(c, n); com_return_stmt(c, n);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment