aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c50
1 files changed, 6 insertions, 44 deletions
diff --git a/lparser.c b/lparser.c
index fb7a1264..77813a74 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1623,59 +1623,21 @@ static void forstat (LexState *ls, int line) {
1623} 1623}
1624 1624
1625 1625
1626/*
1627** Check whether next instruction is a single jump (a 'break', a 'goto'
1628** to a forward label, or a 'goto' to a backward label with no variable
1629** to close). If so, set the name of the 'label' it is jumping to
1630** ("break" for a 'break') or to where it is jumping to ('target') and
1631** return true. If not a single jump, leave input unchanged, to be
1632** handled as a regular statement.
1633*/
1634static int issinglejump (LexState *ls, TString **label, int *target) {
1635 if (testnext(ls, TK_BREAK)) { /* a break? */
1636 *label = luaS_newliteral(ls->L, "break");
1637 return 1;
1638 }
1639 else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME)
1640 return 0; /* not a valid goto */
1641 else {
1642 TString *lname = ls->lookahead.seminfo.ts; /* label's id */
1643 Labeldesc *lb = findlabel(ls, lname);
1644 if (lb) { /* a backward jump? */
1645 /* does it need to close variables? */
1646 if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar))
1647 return 0; /* not a single jump; cannot optimize */
1648 *target = lb->pc;
1649 }
1650 else /* jump forward */
1651 *label = lname;
1652 luaX_next(ls); /* skip goto */
1653 luaX_next(ls); /* skip name */
1654 return 1;
1655 }
1656}
1657
1658
1659static void test_then_block (LexState *ls, int *escapelist) { 1626static void test_then_block (LexState *ls, int *escapelist) {
1660 /* test_then_block -> [IF | ELSEIF] cond THEN block */ 1627 /* test_then_block -> [IF | ELSEIF] cond THEN block */
1661 BlockCnt bl; 1628 BlockCnt bl;
1662 int line;
1663 FuncState *fs = ls->fs; 1629 FuncState *fs = ls->fs;
1664 TString *jlb = NULL;
1665 int target = NO_JUMP;
1666 expdesc v; 1630 expdesc v;
1667 int jf; /* instruction to skip 'then' code (if condition is false) */ 1631 int jf; /* instruction to skip 'then' code (if condition is false) */
1668 luaX_next(ls); /* skip IF or ELSEIF */ 1632 luaX_next(ls); /* skip IF or ELSEIF */
1669 expr(ls, &v); /* read condition */ 1633 expr(ls, &v); /* read condition */
1670 checknext(ls, TK_THEN); 1634 checknext(ls, TK_THEN);
1671 line = ls->linenumber; 1635 if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */
1672 if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */ 1636 int line = ls->linenumber;
1673 luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ 1637 luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */
1638 luaX_next(ls); /* skip 'break' */
1674 enterblock(fs, &bl, 0); /* must enter block before 'goto' */ 1639 enterblock(fs, &bl, 0); /* must enter block before 'goto' */
1675 if (jlb != NULL) /* forward jump? */ 1640 newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
1676 newgotoentry(ls, jlb, line, v.t); /* will be resolved later */
1677 else /* backward jump */
1678 luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */
1679 while (testnext(ls, ';')) {} /* skip semicolons */ 1641 while (testnext(ls, ';')) {} /* skip semicolons */
1680 if (block_follow(ls, 0)) { /* jump is the entire block? */ 1642 if (block_follow(ls, 0)) { /* jump is the entire block? */
1681 leaveblock(fs); 1643 leaveblock(fs);
@@ -1684,7 +1646,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
1684 else /* must skip over 'then' part if condition is false */ 1646 else /* must skip over 'then' part if condition is false */
1685 jf = luaK_jump(fs); 1647 jf = luaK_jump(fs);
1686 } 1648 }
1687 else { /* regular case (not a jump) */ 1649 else { /* regular case (not a break) */
1688 luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ 1650 luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
1689 enterblock(fs, &bl, 0); 1651 enterblock(fs, &bl, 0);
1690 jf = v.f; 1652 jf = v.f;