** Check whether next instruction is a single jump (a 'break', a 'goto' ** to a forward label, or a 'goto' to a backward label with no variable ** to close). If so, set the name of the 'label' it is jumping to ** ("break" for a 'break') or to where it is jumping to ('target') and ** return true. If not a single jump, leave input unchanged, to be ** handled as a regular statement. */
| 1625 | ** handled as a regular statement. |
| 1626 | */ |
| 1627 | static int issinglejump (LexState *ls, TString **label, int *target) { |
| 1628 | if (testnext(ls, TK_BREAK)) { /* a break? */ |
| 1629 | *label = luaS_newliteral(ls->L, "break"); |
| 1630 | return 1; |
| 1631 | } |
| 1632 | else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME) |
| 1633 | return 0; /* not a valid goto */ |
| 1634 | else { |
| 1635 | TString *lname = ls->lookahead.seminfo.ts; /* label's id */ |
| 1636 | Labeldesc *lb = findlabel(ls, lname); |
| 1637 | if (lb) { /* a backward jump? */ |
| 1638 | /* does it need to close variables? */ |
| 1639 | if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar)) |
| 1640 | return 0; /* not a single jump; cannot optimize */ |
| 1641 | *target = lb->pc; |
| 1642 | } |
| 1643 | else /* jump forward */ |
| 1644 | *label = lname; |
| 1645 | luaX_next(ls); /* skip goto */ |
| 1646 | luaX_next(ls); /* skip name */ |
| 1647 | return 1; |
| 1648 | } |
| 1649 | } |
| 1650 | |
| 1651 | |
| 1652 | static void test_then_block (LexState *ls, int *escapelist) { |