]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
New syntax: semicolons, continue statement.
authorGuido van Rossum <guido@python.org>
Sat, 27 Jul 1991 21:34:52 +0000 (21:34 +0000)
committerGuido van Rossum <guido@python.org>
Sat, 27 Jul 1991 21:34:52 +0000 (21:34 +0000)
For the latter we must keep track of the current block's type.
(We can't continue through a try statement, sigh.()

Python/compile.c

index 71d13bc2f16249db41798c5a1b5ae203a4609397..4dc3d9f19a27384fb4cb868bcf2c866f2e366fc7 100644 (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;