aboutsummaryrefslogtreecommitdiff
path: root/src/lua/lparser.c
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-01-05 16:48:53 +0800
committerLi Jin <dragon-fly@qq.com>2021-01-05 16:48:53 +0800
commit71b9532659abb531bd1597d88451426dcc895824 (patch)
treec9b50856b37f759c9a31e1a6e761e77b51996fa6 /src/lua/lparser.c
parente3a31f9945053d8e8d9e4ef3d2e4c9abe563cff2 (diff)
downloadyuescript-71b9532659abb531bd1597d88451426dcc895824.tar.gz
yuescript-71b9532659abb531bd1597d88451426dcc895824.tar.bz2
yuescript-71b9532659abb531bd1597d88451426dcc895824.zip
update Lua.
Diffstat (limited to 'src/lua/lparser.c')
-rw-r--r--src/lua/lparser.c104
1 files changed, 33 insertions, 71 deletions
diff --git a/src/lua/lparser.c b/src/lua/lparser.c
index bcdcfb6..249ba9a 100644
--- a/src/lua/lparser.c
+++ b/src/lua/lparser.c
@@ -222,26 +222,26 @@ static Vardesc *getlocalvardesc (FuncState *fs, int vidx) {
222 222
223 223
224/* 224/*
225** Convert 'nvar', a compiler index level, to it corresponding 225** Convert 'nvar', a compiler index level, to its corresponding
226** stack index level. For that, search for the highest variable 226** register. For that, search for the highest variable below that level
227** below that level that is in the stack and uses its stack 227** that is in a register and uses its register index ('ridx') plus one.
228** index ('sidx').
229*/ 228*/
230static int stacklevel (FuncState *fs, int nvar) { 229static int reglevel (FuncState *fs, int nvar) {
231 while (nvar-- > 0) { 230 while (nvar-- > 0) {
232 Vardesc *vd = getlocalvardesc(fs, nvar); /* get variable */ 231 Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */
233 if (vd->vd.kind != RDKCTC) /* is in the stack? */ 232 if (vd->vd.kind != RDKCTC) /* is in a register? */
234 return vd->vd.sidx + 1; 233 return vd->vd.ridx + 1;
235 } 234 }
236 return 0; /* no variables in the stack */ 235 return 0; /* no variables in registers */
237} 236}
238 237
239 238
240/* 239/*
241** Return the number of variables in the stack for function 'fs' 240** Return the number of variables in the register stack for the given
241** function.
242*/ 242*/
243int luaY_nvarstack (FuncState *fs) { 243int luaY_nvarstack (FuncState *fs) {
244 return stacklevel(fs, fs->nactvar); 244 return reglevel(fs, fs->nactvar);
245} 245}
246 246
247 247
@@ -267,7 +267,7 @@ static void init_var (FuncState *fs, expdesc *e, int vidx) {
267 e->f = e->t = NO_JUMP; 267 e->f = e->t = NO_JUMP;
268 e->k = VLOCAL; 268 e->k = VLOCAL;
269 e->u.var.vidx = vidx; 269 e->u.var.vidx = vidx;
270 e->u.var.sidx = getlocalvardesc(fs, vidx)->vd.sidx; 270 e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx;
271} 271}
272 272
273 273
@@ -310,12 +310,12 @@ static void check_readonly (LexState *ls, expdesc *e) {
310*/ 310*/
311static void adjustlocalvars (LexState *ls, int nvars) { 311static void adjustlocalvars (LexState *ls, int nvars) {
312 FuncState *fs = ls->fs; 312 FuncState *fs = ls->fs;
313 int stklevel = luaY_nvarstack(fs); 313 int reglevel = luaY_nvarstack(fs);
314 int i; 314 int i;
315 for (i = 0; i < nvars; i++) { 315 for (i = 0; i < nvars; i++) {
316 int vidx = fs->nactvar++; 316 int vidx = fs->nactvar++;
317 Vardesc *var = getlocalvardesc(fs, vidx); 317 Vardesc *var = getlocalvardesc(fs, vidx);
318 var->vd.sidx = stklevel++; 318 var->vd.ridx = reglevel++;
319 var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); 319 var->vd.pidx = registerlocalvar(ls, fs, var->vd.name);
320 } 320 }
321} 321}
@@ -366,7 +366,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) {
366 FuncState *prev = fs->prev; 366 FuncState *prev = fs->prev;
367 if (v->k == VLOCAL) { 367 if (v->k == VLOCAL) {
368 up->instack = 1; 368 up->instack = 1;
369 up->idx = v->u.var.sidx; 369 up->idx = v->u.var.ridx;
370 up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind; 370 up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind;
371 lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name)); 371 lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name));
372 } 372 }
@@ -620,7 +620,7 @@ static void movegotosout (FuncState *fs, BlockCnt *bl) {
620 for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ 620 for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */
621 Labeldesc *gt = &gl->arr[i]; 621 Labeldesc *gt = &gl->arr[i];
622 /* leaving a variable scope? */ 622 /* leaving a variable scope? */
623 if (stacklevel(fs, gt->nactvar) > stacklevel(fs, bl->nactvar)) 623 if (reglevel(fs, gt->nactvar) > reglevel(fs, bl->nactvar))
624 gt->close |= bl->upval; /* jump may need a close */ 624 gt->close |= bl->upval; /* jump may need a close */
625 gt->nactvar = bl->nactvar; /* update goto level */ 625 gt->nactvar = bl->nactvar; /* update goto level */
626 } 626 }
@@ -661,7 +661,7 @@ static void leaveblock (FuncState *fs) {
661 BlockCnt *bl = fs->bl; 661 BlockCnt *bl = fs->bl;
662 LexState *ls = fs->ls; 662 LexState *ls = fs->ls;
663 int hasclose = 0; 663 int hasclose = 0;
664 int stklevel = stacklevel(fs, bl->nactvar); /* level outside the block */ 664 int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */
665 if (bl->isloop) /* fix pending breaks? */ 665 if (bl->isloop) /* fix pending breaks? */
666 hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); 666 hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0);
667 if (!hasclose && bl->previous && bl->upval) 667 if (!hasclose && bl->previous && bl->upval)
@@ -945,7 +945,7 @@ static void setvararg (FuncState *fs, int nparams) {
945 945
946 946
947static void parlist (LexState *ls) { 947static void parlist (LexState *ls) {
948 /* parlist -> [ param { ',' param } ] */ 948 /* parlist -> [ {NAME ','} (NAME | '...') ] */
949 FuncState *fs = ls->fs; 949 FuncState *fs = ls->fs;
950 Proto *f = fs->f; 950 Proto *f = fs->f;
951 int nparams = 0; 951 int nparams = 0;
@@ -953,12 +953,12 @@ static void parlist (LexState *ls) {
953 if (ls->t.token != ')') { /* is 'parlist' not empty? */ 953 if (ls->t.token != ')') { /* is 'parlist' not empty? */
954 do { 954 do {
955 switch (ls->t.token) { 955 switch (ls->t.token) {
956 case TK_NAME: { /* param -> NAME */ 956 case TK_NAME: {
957 new_localvar(ls, str_checkname(ls)); 957 new_localvar(ls, str_checkname(ls));
958 nparams++; 958 nparams++;
959 break; 959 break;
960 } 960 }
961 case TK_DOTS: { /* param -> '...' */ 961 case TK_DOTS: {
962 luaX_next(ls); 962 luaX_next(ls);
963 isvararg = 1; 963 isvararg = 1;
964 break; 964 break;
@@ -1330,13 +1330,13 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
1330 } 1330 }
1331 } 1331 }
1332 else { /* table is a register */ 1332 else { /* table is a register */
1333 if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.sidx) { 1333 if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.ridx) {
1334 conflict = 1; /* table is the local being assigned now */ 1334 conflict = 1; /* table is the local being assigned now */
1335 lh->v.u.ind.t = extra; /* assignment will use safe copy */ 1335 lh->v.u.ind.t = extra; /* assignment will use safe copy */
1336 } 1336 }
1337 /* is index the local being assigned? */ 1337 /* is index the local being assigned? */
1338 if (lh->v.k == VINDEXED && v->k == VLOCAL && 1338 if (lh->v.k == VINDEXED && v->k == VLOCAL &&
1339 lh->v.u.ind.idx == v->u.var.sidx) { 1339 lh->v.u.ind.idx == v->u.var.ridx) {
1340 conflict = 1; 1340 conflict = 1;
1341 lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ 1341 lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */
1342 } 1342 }
@@ -1346,7 +1346,7 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
1346 if (conflict) { 1346 if (conflict) {
1347 /* copy upvalue/local value to a temporary (in position 'extra') */ 1347 /* copy upvalue/local value to a temporary (in position 'extra') */
1348 if (v->k == VLOCAL) 1348 if (v->k == VLOCAL)
1349 luaK_codeABC(fs, OP_MOVE, extra, v->u.var.sidx, 0); 1349 luaK_codeABC(fs, OP_MOVE, extra, v->u.var.ridx, 0);
1350 else 1350 else
1351 luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0); 1351 luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0);
1352 luaK_reserveregs(fs, 1); 1352 luaK_reserveregs(fs, 1);
@@ -1411,7 +1411,7 @@ static void gotostat (LexState *ls) {
1411 newgotoentry(ls, name, line, luaK_jump(fs)); 1411 newgotoentry(ls, name, line, luaK_jump(fs));
1412 else { /* found a label */ 1412 else { /* found a label */
1413 /* backward jump; will be resolved here */ 1413 /* backward jump; will be resolved here */
1414 int lblevel = stacklevel(fs, lb->nactvar); /* label level */ 1414 int lblevel = reglevel(fs, lb->nactvar); /* label level */
1415 if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ 1415 if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */
1416 luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); 1416 luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0);
1417 /* create jump and link it to the label */ 1417 /* create jump and link it to the label */
@@ -1488,7 +1488,7 @@ static void repeatstat (LexState *ls, int line) {
1488 if (bl2.upval) { /* upvalues? */ 1488 if (bl2.upval) { /* upvalues? */
1489 int exit = luaK_jump(fs); /* normal exit must jump over fix */ 1489 int exit = luaK_jump(fs); /* normal exit must jump over fix */
1490 luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ 1490 luaK_patchtohere(fs, condexit); /* repetition must close upvalues */
1491 luaK_codeABC(fs, OP_CLOSE, stacklevel(fs, bl2.nactvar), 0, 0); 1491 luaK_codeABC(fs, OP_CLOSE, reglevel(fs, bl2.nactvar), 0, 0);
1492 condexit = luaK_jump(fs); /* repeat after closing upvalues */ 1492 condexit = luaK_jump(fs); /* repeat after closing upvalues */
1493 luaK_patchtohere(fs, exit); /* normal exit comes to here */ 1493 luaK_patchtohere(fs, exit); /* normal exit comes to here */
1494 } 1494 }
@@ -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;
@@ -1746,13 +1708,13 @@ static void checktoclose (LexState *ls, int level) {
1746 FuncState *fs = ls->fs; 1708 FuncState *fs = ls->fs;
1747 markupval(fs, level + 1); 1709 markupval(fs, level + 1);
1748 fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ 1710 fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
1749 luaK_codeABC(fs, OP_TBC, stacklevel(fs, level), 0, 0); 1711 luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0);
1750 } 1712 }
1751} 1713}
1752 1714
1753 1715
1754static void localstat (LexState *ls) { 1716static void localstat (LexState *ls) {
1755 /* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */ 1717 /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */
1756 FuncState *fs = ls->fs; 1718 FuncState *fs = ls->fs;
1757 int toclose = -1; /* index of to-be-closed variable (if any) */ 1719 int toclose = -1; /* index of to-be-closed variable (if any) */
1758 Vardesc *var; /* last variable */ 1720 Vardesc *var; /* last variable */