aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-04 15:34:43 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-04 15:34:43 -0200
commit7cc0e63d8a5bd45eabd328c398f02a933e07746d (patch)
tree94a00b4e19c3c1ea0c6e3ee2e3dbb036d960f5c0
parenta4a8914c2097bdcaaa4e82c5fd1c9b0c7371e432 (diff)
downloadlua-7cc0e63d8a5bd45eabd328c398f02a933e07746d.tar.gz
lua-7cc0e63d8a5bd45eabd328c398f02a933e07746d.tar.bz2
lua-7cc0e63d8a5bd45eabd328c398f02a933e07746d.zip
first implementation of 'goto'
-rw-r--r--ldo.c11
-rw-r--r--llex.h4
-rw-r--r--lparser.c188
-rw-r--r--lparser.h47
4 files changed, 227 insertions, 23 deletions
diff --git a/ldo.c b/ldo.c
index dc489446..519aa85a 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.89 2010/09/30 17:21:31 roberto Exp roberto $ 2** $Id: ldo.c,v 2.90 2010/10/25 19:01:37 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -617,6 +617,8 @@ struct SParser { /* data to `f_parser' */
617 ZIO *z; 617 ZIO *z;
618 Mbuffer buff; /* buffer to be used by the scanner */ 618 Mbuffer buff; /* buffer to be used by the scanner */
619 Varlist varl; /* list of local variables (to be used by the parser) */ 619 Varlist varl; /* list of local variables (to be used by the parser) */
620 Gotolist gtl; /* list of pending gotos (") */
621 Labellist labell; /* list of active labels (") */
620 const char *name; 622 const char *name;
621}; 623};
622 624
@@ -628,7 +630,8 @@ static void f_parser (lua_State *L, void *ud) {
628 int c = luaZ_lookahead(p->z); 630 int c = luaZ_lookahead(p->z);
629 tf = (c == LUA_SIGNATURE[0]) 631 tf = (c == LUA_SIGNATURE[0])
630 ? luaU_undump(L, p->z, &p->buff, p->name) 632 ? luaU_undump(L, p->z, &p->buff, p->name)
631 : luaY_parser(L, p->z, &p->buff, &p->varl, p->name); 633 : luaY_parser(L, p->z, &p->buff, &p->varl,
634 &p->gtl, &p->labell, p->name);
632 setptvalue2s(L, L->top, tf); 635 setptvalue2s(L, L->top, tf);
633 incr_top(L); 636 incr_top(L);
634 cl = luaF_newLclosure(L, tf); 637 cl = luaF_newLclosure(L, tf);
@@ -644,10 +647,14 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {
644 L->nny++; /* cannot yield during parsing */ 647 L->nny++; /* cannot yield during parsing */
645 p.z = z; p.name = name; 648 p.z = z; p.name = name;
646 p.varl.actvar = NULL; p.varl.nactvar = p.varl.actvarsize = 0; 649 p.varl.actvar = NULL; p.varl.nactvar = p.varl.actvarsize = 0;
650 p.gtl.gt = NULL; p.gtl.ngt = p.gtl.gtsize = 0;
651 p.labell.label = NULL; p.labell.nlabel = p.labell.labelsize = 0;
647 luaZ_initbuffer(L, &p.buff); 652 luaZ_initbuffer(L, &p.buff);
648 status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); 653 status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
649 luaZ_freebuffer(L, &p.buff); 654 luaZ_freebuffer(L, &p.buff);
650 luaM_freearray(L, p.varl.actvar, p.varl.actvarsize); 655 luaM_freearray(L, p.varl.actvar, p.varl.actvarsize);
656 luaM_freearray(L, p.gtl.gt, p.gtl.gtsize);
657 luaM_freearray(L, p.labell.label, p.labell.labelsize);
651 L->nny--; 658 L->nny--;
652 return status; 659 return status;
653} 660}
diff --git a/llex.h b/llex.h
index aa3724d0..65409279 100644
--- a/llex.h
+++ b/llex.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llex.h,v 1.65 2010/04/05 16:35:37 roberto Exp roberto $ 2** $Id: llex.h,v 1.66 2011/02/02 14:55:17 roberto Exp roberto $
3** Lexical Analyzer 3** Lexical Analyzer
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -59,6 +59,8 @@ typedef struct LexState {
59 ZIO *z; /* input stream */ 59 ZIO *z; /* input stream */
60 Mbuffer *buff; /* buffer for tokens */ 60 Mbuffer *buff; /* buffer for tokens */
61 struct Varlist *varl; /* list of all active local variables */ 61 struct Varlist *varl; /* list of all active local variables */
62 struct Gotolist *gtl; /* list of pending gotos */
63 struct Labellist *labell; /* list of active labels */
62 TString *source; /* current source name */ 64 TString *source; /* current source name */
63 TString *envn; /* environment variable name */ 65 TString *envn; /* environment variable name */
64 char decpoint; /* locale decimal point */ 66 char decpoint; /* locale decimal point */
diff --git a/lparser.c b/lparser.c
index b2d55c68..52c1bbd0 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.95 2011/01/26 16:30:02 roberto Exp roberto $ 2** $Id: lparser.c,v 2.96 2011/02/01 18:03:10 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -42,7 +42,9 @@
42typedef struct BlockCnt { 42typedef struct BlockCnt {
43 struct BlockCnt *previous; /* chain */ 43 struct BlockCnt *previous; /* chain */
44 int breaklist; /* list of jumps out of this loop */ 44 int breaklist; /* list of jumps out of this loop */
45 lu_byte nactvar; /* # active locals outside the breakable structure */ 45 int firstlabel; /* index (in Labellist) of first label in this block */
46 int firstgoto; /* index (in Gotolist) of first pending goto in this block */
47 lu_byte nactvar; /* # active locals outside the block */
46 lu_byte upval; /* true if some variable in the block is an upvalue */ 48 lu_byte upval; /* true if some variable in the block is an upvalue */
47 lu_byte isbreakable; /* true if `block' is a loop */ 49 lu_byte isbreakable; /* true if `block' is a loop */
48} BlockCnt; 50} BlockCnt;
@@ -52,7 +54,7 @@ typedef struct BlockCnt {
52/* 54/*
53** prototypes for recursive non-terminal functions 55** prototypes for recursive non-terminal functions
54*/ 56*/
55static void chunk (LexState *ls); 57static void statlist (LexState *ls);
56static void expr (LexState *ls, expdesc *v); 58static void expr (LexState *ls, expdesc *v);
57 59
58 60
@@ -172,7 +174,7 @@ static void new_localvar (LexState *ls, TString *name) {
172 checklimit(fs, vl->nactvar + 1 - fs->firstlocal, 174 checklimit(fs, vl->nactvar + 1 - fs->firstlocal,
173 MAXVARS, "local variables"); 175 MAXVARS, "local variables");
174 luaM_growvector(ls->L, vl->actvar, vl->nactvar + 1, 176 luaM_growvector(ls->L, vl->actvar, vl->nactvar + 1,
175 vl->actvarsize, vardesc, MAX_INT, "local variables"); 177 vl->actvarsize, Vardesc, MAX_INT, "local variables");
176 vl->actvar[vl->nactvar++].idx = cast(unsigned short, reg); 178 vl->actvar[vl->nactvar++].idx = cast(unsigned short, reg);
177} 179}
178 180
@@ -327,10 +329,93 @@ static void enterlevel (LexState *ls) {
327#define leavelevel(ls) (G((ls)->L)->nCcalls--) 329#define leavelevel(ls) (G((ls)->L)->nCcalls--)
328 330
329 331
332static void closegoto (LexState *ls, int g, Labeldesc *label) {
333 int i;
334 FuncState *fs = ls->fs;
335 Gotodesc *gt = &ls->gtl->gt[g];
336 lua_assert(gt->name == label->name);
337 if (gt->currlevel < label->nactvar) {
338 const char *msg = luaO_pushfstring(ls->L,
339 "<goto> at line %d attemps to jump into the scope of local " LUA_QS,
340 gt->line, getstr(getlocvar(fs, gt->currlevel)->varname));;
341 luaX_syntaxerror(ls, msg);
342 }
343 luaK_patchlist(fs, gt->pc, label->pc);
344 /* remove goto from pending list */
345 for (i = g; i < ls->gtl->ngt - 1; i++)
346 ls->gtl->gt[i] = ls->gtl->gt[i + 1];
347 ls->gtl->ngt--;
348}
349
350
351/*
352** try to close a goto with existing labels; this solves backward jumps
353*/
354static int findlabel (LexState *ls, int g) {
355 int i;
356 BlockCnt *bl = ls->fs->bl;
357 Labellist *labell = ls->labell;
358 Gotodesc *gt = &ls->gtl->gt[g];
359 /* check labels in current block for a match */
360 for (i = bl->firstlabel; i < labell->nlabel; i++) {
361 Labeldesc *lb = &labell->label[i];
362 if (lb->name == gt->name) {
363 lua_assert(labell->label[i].pc <= gt->pc);
364 if (gt->currlevel > lb->nactvar &&
365 (bl->upval || ls->labell->nlabel > bl->firstlabel))
366 luaK_patchclose(ls->fs, gt->pc, lb->nactvar);
367 closegoto(ls, g, lb); /* close it */
368 return 1;
369 }
370 }
371 return 0; /* label not found; cannot close goto */
372}
373
374
375/*
376** check whether new label 'lb' matches any pending goto in current
377** block; solves forward jumps
378*/
379static void findgotos (LexState *ls, Labeldesc *lb) {
380 int i;
381 Gotolist *gtl = ls->gtl;
382 for (i = ls->fs->bl->firstgoto; i < gtl->ngt; i++) {
383 if (gtl->gt[i].name == lb->name)
384 closegoto(ls, i, lb);
385 }
386}
387
388
389/*
390** "export" pending gotos to outer level, to check them against
391** outer labels; if the block being exited has upvalues, and
392** the goto exists the scope of any variable (which can be the
393** upvalue), close those variables being exited.
394*/
395static void movegotosout (FuncState *fs, BlockCnt *bl) {
396 int i = bl->firstgoto;
397 LexState *ls = fs->ls;
398 /* correct pending gotos to current block and try to close it
399 with visible labels */
400 while (i < ls->gtl->ngt) {
401 Gotodesc *gt = &ls->gtl->gt[i];
402 if (gt->currlevel > bl->nactvar) {
403 if (bl->upval)
404 luaK_patchclose(fs, gt->pc, bl->nactvar);
405 gt->currlevel = bl->nactvar;
406 }
407 if (!findlabel(ls, i))
408 i++; /* move to next one */
409 }
410}
411
412
330static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { 413static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
331 bl->breaklist = NO_JUMP; 414 bl->breaklist = NO_JUMP;
332 bl->isbreakable = isbreakable; 415 bl->isbreakable = isbreakable;
333 bl->nactvar = fs->nactvar; 416 bl->nactvar = fs->nactvar;
417 bl->firstlabel = fs->ls->labell->nlabel;
418 bl->firstgoto = fs->ls->gtl->ngt;
334 bl->upval = 0; 419 bl->upval = 0;
335 bl->previous = fs->bl; 420 bl->previous = fs->bl;
336 fs->bl = bl; 421 fs->bl = bl;
@@ -342,6 +427,8 @@ static void leaveblock (FuncState *fs) {
342 BlockCnt *bl = fs->bl; 427 BlockCnt *bl = fs->bl;
343 fs->bl = bl->previous; 428 fs->bl = bl->previous;
344 removevars(fs, bl->nactvar); 429 removevars(fs, bl->nactvar);
430 fs->ls->labell->nlabel = bl->firstlabel; /* remove local labels */
431 movegotosout(fs, bl);
345 if (bl->upval) 432 if (bl->upval)
346 luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); 433 luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
347 /* a block either controls scope or breaks (never both) */ 434 /* a block either controls scope or breaks (never both) */
@@ -445,8 +532,24 @@ static void open_mainfunc (LexState *ls, FuncState *fs) {
445} 532}
446 533
447 534
535static void mainblock (LexState *ls, FuncState *fs) {
536 BlockCnt bl;
537 enterblock(fs, &bl, 0);
538 statlist(ls); /* read main block */
539 if (bl.firstgoto < ls->gtl->ngt) { /* check pending gotos */
540 Gotodesc *gt = &ls->gtl->gt[bl.firstgoto];
541 const char *msg = luaO_pushfstring(ls->L,
542 "label " LUA_QS " (<goto> at line %d) undefined",
543 getstr(gt->name), gt->line);
544 luaX_syntaxerror(ls, msg);
545 }
546 bl.upval = 0; /* RETURN will close any pending upvalue */
547 leaveblock(fs);
548}
549
550
448Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Varlist *varl, 551Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Varlist *varl,
449 const char *name) { 552 Gotolist *gtl, Labellist *labell, const char *name) {
450 LexState lexstate; 553 LexState lexstate;
451 FuncState funcstate; 554 FuncState funcstate;
452 TString *tname = luaS_new(L, name); 555 TString *tname = luaS_new(L, name);
@@ -454,10 +557,12 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Varlist *varl,
454 incr_top(L); 557 incr_top(L);
455 lexstate.buff = buff; 558 lexstate.buff = buff;
456 lexstate.varl = varl; 559 lexstate.varl = varl;
560 lexstate.gtl = gtl;
561 lexstate.labell = labell;
457 luaX_setinput(L, &lexstate, z, tname); 562 luaX_setinput(L, &lexstate, z, tname);
458 open_mainfunc(&lexstate, &funcstate); 563 open_mainfunc(&lexstate, &funcstate);
459 luaX_next(&lexstate); /* read first token */ 564 luaX_next(&lexstate); /* read first token */
460 chunk(&lexstate); /* read main chunk */ 565 mainblock(&lexstate, &funcstate);
461 check(&lexstate, TK_EOS); 566 check(&lexstate, TK_EOS);
462 close_func(&lexstate); 567 close_func(&lexstate);
463 L->top--; /* pop name */ 568 L->top--; /* pop name */
@@ -645,7 +750,7 @@ static void parlist (LexState *ls) {
645 750
646 751
647static void body (LexState *ls, expdesc *e, int needself, int line) { 752static void body (LexState *ls, expdesc *e, int needself, int line) {
648 /* body -> `(' parlist `)' chunk END */ 753 /* body -> `(' parlist `)' block END */
649 FuncState new_fs; 754 FuncState new_fs;
650 open_func(ls, &new_fs); 755 open_func(ls, &new_fs);
651 new_fs.f->linedefined = line; 756 new_fs.f->linedefined = line;
@@ -656,7 +761,7 @@ static void body (LexState *ls, expdesc *e, int needself, int line) {
656 } 761 }
657 parlist(ls); 762 parlist(ls);
658 checknext(ls, ')'); 763 checknext(ls, ')');
659 chunk(ls); 764 mainblock(ls, &new_fs);
660 new_fs.f->lastlinedefined = ls->linenumber; 765 new_fs.f->lastlinedefined = ls->linenumber;
661 check_match(ls, TK_END, TK_FUNCTION, line); 766 check_match(ls, TK_END, TK_FUNCTION, line);
662 codeclosure(ls, new_fs.f, e); 767 codeclosure(ls, new_fs.f, e);
@@ -949,11 +1054,11 @@ static int block_follow (int token) {
949 1054
950 1055
951static void block (LexState *ls) { 1056static void block (LexState *ls) {
952 /* block -> chunk */ 1057 /* block -> statlist */
953 FuncState *fs = ls->fs; 1058 FuncState *fs = ls->fs;
954 BlockCnt bl; 1059 BlockCnt bl;
955 enterblock(fs, &bl, 0); 1060 enterblock(fs, &bl, 0);
956 chunk(ls); 1061 statlist(ls);
957 lua_assert(bl.breaklist == NO_JUMP); 1062 lua_assert(bl.breaklist == NO_JUMP);
958 leaveblock(fs); 1063 leaveblock(fs);
959} 1064}
@@ -1043,6 +1148,13 @@ static int cond (LexState *ls) {
1043} 1148}
1044 1149
1045 1150
1151/* code a break statement. The last 'if' decides the need to close
1152 upvalues when leaving the block. If the block has upvalues, it
1153 must be closed. If it has local variables and any label
1154 before the break, those variables must be closed too, as they
1155 may be used as upvalues after the break and through a goto
1156 be exited through this break.
1157*/
1046static void breakstat (LexState *ls) { 1158static void breakstat (LexState *ls) {
1047 FuncState *fs = ls->fs; 1159 FuncState *fs = ls->fs;
1048 BlockCnt *bl = fs->bl; 1160 BlockCnt *bl = fs->bl;
@@ -1054,11 +1166,49 @@ static void breakstat (LexState *ls) {
1054 if (!bl) 1166 if (!bl)
1055 luaX_syntaxerror(ls, "no loop to break"); 1167 luaX_syntaxerror(ls, "no loop to break");
1056 luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); 1168 luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
1057 if (upval) 1169 if (upval ||
1170 (fs->nactvar > bl->nactvar &&
1171 ls->labell->nlabel > bl->firstlabel))
1058 luaK_patchclose(fs, bl->breaklist, bl->nactvar); 1172 luaK_patchclose(fs, bl->breaklist, bl->nactvar);
1059} 1173}
1060 1174
1061 1175
1176static void gotostat (LexState *ls, TString *label, int line) {
1177 Gotolist *gtl = ls->gtl;
1178 int g = gtl->ngt; /* index of new goto being created */
1179 /* create new entry for this goto */
1180 luaM_growvector(ls->L, gtl->gt, gtl->ngt, gtl->gtsize,
1181 Gotodesc, MAX_INT, "labels");
1182 gtl->gt[g].name = label;
1183 gtl->gt[g].line = line;
1184 gtl->gt[g].currlevel = ls->fs->nactvar;
1185 gtl->gt[g].pc = luaK_jump(ls->fs); /* create jump instruction */
1186 gtl->ngt++;
1187 findlabel(ls, g);
1188}
1189
1190
1191static void labelstat (LexState *ls, TString *label) {
1192 /* label -> '@' NAME ':' */
1193 FuncState *fs = ls->fs;
1194 Labellist *labell = ls->labell;
1195 int l = labell->nlabel; /* index of new label being created */
1196 checknext(ls, ':');
1197 /* create new entry for this label */
1198 luaM_growvector(ls->L, labell->label, labell->nlabel, labell->labelsize,
1199 Labeldesc, MAX_INT, "labels");
1200 labell->label[l].name = label;
1201 labell->label[l].pc = fs->pc;
1202 /* if label is last statement in the block,
1203 assume that local variables are already out of scope */
1204 labell->label[l].nactvar = (ls->t.token == TK_END)
1205 ? fs->bl->nactvar
1206 : fs->nactvar;
1207 labell->nlabel++;
1208 findgotos(ls, &labell->label[l]);
1209}
1210
1211
1062static void whilestat (LexState *ls, int line) { 1212static void whilestat (LexState *ls, int line) {
1063 /* whilestat -> WHILE cond DO block END */ 1213 /* whilestat -> WHILE cond DO block END */
1064 FuncState *fs = ls->fs; 1214 FuncState *fs = ls->fs;
@@ -1087,7 +1237,7 @@ static void repeatstat (LexState *ls, int line) {
1087 enterblock(fs, &bl1, 1); /* loop block */ 1237 enterblock(fs, &bl1, 1); /* loop block */
1088 enterblock(fs, &bl2, 0); /* scope block */ 1238 enterblock(fs, &bl2, 0); /* scope block */
1089 luaX_next(ls); /* skip REPEAT */ 1239 luaX_next(ls); /* skip REPEAT */
1090 chunk(ls); 1240 statlist(ls);
1091 check_match(ls, TK_UNTIL, TK_REPEAT, line); 1241 check_match(ls, TK_UNTIL, TK_REPEAT, line);
1092 condexit = cond(ls); /* read condition (inside scope block) */ 1242 condexit = cond(ls); /* read condition (inside scope block) */
1093 if (!bl2.upval) { /* no upvalues? */ 1243 if (!bl2.upval) { /* no upvalues? */
@@ -1382,6 +1532,11 @@ static int statement (LexState *ls) {
1382 localstat(ls); 1532 localstat(ls);
1383 return 0; 1533 return 0;
1384 } 1534 }
1535 case '@': { /* stat -> label */
1536 luaX_next(ls); /* skip '@' */
1537 labelstat(ls, str_checkname(ls));
1538 return 0;
1539 }
1385 case TK_RETURN: { /* stat -> retstat */ 1540 case TK_RETURN: { /* stat -> retstat */
1386 luaX_next(ls); /* skip RETURN */ 1541 luaX_next(ls); /* skip RETURN */
1387 retstat(ls); 1542 retstat(ls);
@@ -1392,6 +1547,11 @@ static int statement (LexState *ls) {
1392 breakstat(ls); 1547 breakstat(ls);
1393 return 1; /* must be last statement */ 1548 return 1; /* must be last statement */
1394 } 1549 }
1550 case TK_GOTO: { /* stat -> 'goto' NAME */
1551 luaX_next(ls); /* skip GOTO */
1552 gotostat(ls, str_checkname(ls), line);
1553 return 0;
1554 }
1395 default: { /* stat -> func | assignment */ 1555 default: { /* stat -> func | assignment */
1396 exprstat(ls); 1556 exprstat(ls);
1397 return 0; 1557 return 0;
@@ -1400,8 +1560,8 @@ static int statement (LexState *ls) {
1400} 1560}
1401 1561
1402 1562
1403static void chunk (LexState *ls) { 1563static void statlist (LexState *ls) {
1404 /* chunk -> { stat [`;'] } */ 1564 /* statlist -> { stat [`;'] } */
1405 int islast = 0; 1565 int islast = 0;
1406 enterlevel(ls); 1566 enterlevel(ls);
1407 while (!islast && !block_follow(ls->t.token)) { 1567 while (!islast && !block_follow(ls->t.token)) {
diff --git a/lparser.h b/lparser.h
index 945a14a5..b433a02a 100644
--- a/lparser.h
+++ b/lparser.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.h,v 1.64 2010/07/02 20:42:40 roberto Exp roberto $ 2** $Id: lparser.h,v 1.65 2010/07/07 16:27:29 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -53,19 +53,53 @@ typedef struct expdesc {
53} expdesc; 53} expdesc;
54 54
55 55
56typedef struct vardesc { 56/* description of active local variable */
57 unsigned short idx; 57typedef struct Vardesc {
58} vardesc; 58 unsigned short idx; /* variable index in stack */
59} Vardesc;
59 60
60 61
61/* list of all active local variables */ 62/* list of all active local variables */
62typedef struct Varlist { 63typedef struct Varlist {
63 vardesc *actvar; 64 Vardesc *actvar;
64 int nactvar; 65 int nactvar;
65 int actvarsize; 66 int actvarsize;
66} Varlist; 67} Varlist;
67 68
68 69
70/* description of pending goto statement */
71typedef struct Gotodesc {
72 TString *name;
73 int pc; /* where it is coded */
74 int line; /* line where it appeared */
75 lu_byte currlevel; /* variable level where it appears in current block */
76} Gotodesc;
77
78
79/* list of pending gotos */
80typedef struct Gotolist {
81 Gotodesc *gt;
82 int ngt;
83 int gtsize;
84} Gotolist;
85
86
87/* description of active labels */
88typedef struct Labeldesc {
89 TString *name;
90 int pc; /* label position */
91 lu_byte nactvar; /* variable level where it appears in current block */
92} Labeldesc;
93
94
95/* list of active labels */
96typedef struct Labellist {
97 Labeldesc *label;
98 int nlabel;
99 int labelsize;
100} Labellist;
101
102
69struct BlockCnt; /* defined in lparser.c */ 103struct BlockCnt; /* defined in lparser.c */
70 104
71 105
@@ -91,7 +125,8 @@ typedef struct FuncState {
91 125
92 126
93LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, 127LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
94 Varlist *varl, const char *name); 128 Varlist *varl, Gotolist *gtl,
129 Labellist *labell, const char *name);
95 130
96 131
97#endif 132#endif