diff options
author | Li Jin <dragon-fly@qq.com> | 2021-01-05 16:48:53 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2021-01-05 16:48:53 +0800 |
commit | 71b9532659abb531bd1597d88451426dcc895824 (patch) | |
tree | c9b50856b37f759c9a31e1a6e761e77b51996fa6 /src/lua/lparser.c | |
parent | e3a31f9945053d8e8d9e4ef3d2e4c9abe563cff2 (diff) | |
download | yuescript-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.c | 104 |
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 | */ |
230 | static int stacklevel (FuncState *fs, int nvar) { | 229 | static 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 | */ |
243 | int luaY_nvarstack (FuncState *fs) { | 243 | int 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 | */ |
311 | static void adjustlocalvars (LexState *ls, int nvars) { | 311 | static 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 | ||
947 | static void parlist (LexState *ls) { | 947 | static 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 | */ | ||
1634 | static 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 | |||
1659 | static void test_then_block (LexState *ls, int *escapelist) { | 1626 | static 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 | ||
1754 | static void localstat (LexState *ls) { | 1716 | static 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 */ |