aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lcode.c92
-rw-r--r--lcode.h8
-rw-r--r--llex.c5
-rw-r--r--llex.h4
-rw-r--r--lparser.c169
-rw-r--r--lparser.h7
6 files changed, 168 insertions, 117 deletions
diff --git a/lcode.c b/lcode.c
index 137cfcdc..de4c3623 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 1.18 2000/03/24 17:26:08 roberto Exp roberto $ 2** $Id: lcode.c,v 1.19 2000/04/04 20:48:44 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -23,6 +23,18 @@ void luaK_error (LexState *ls, const char *msg) {
23 luaX_error(ls, msg, ls->token); 23 luaX_error(ls, msg, ls->token);
24} 24}
25 25
26/*
27** Returns the the previous instruction, for optimizations.
28** If there is a jump target between this and the current instruction,
29** returns a dummy instruction to avoid wrong optimizations.
30*/
31static Instruction previous_instruction (FuncState *fs) {
32 if (fs->pc > fs->lasttarget) /* no jumps to current position? */
33 return fs->f->code[fs->pc-1]; /* returns previous instruction */
34 else
35 return CREATE_0(OP_END); /* no optimizations after an `END' */
36}
37
26 38
27int luaK_code (FuncState *fs, Instruction i, int delta) { 39int luaK_code (FuncState *fs, Instruction i, int delta) {
28 luaK_deltastack(fs, delta); 40 luaK_deltastack(fs, delta);
@@ -48,19 +60,6 @@ int luaK_AB(FuncState *fs, OpCode o, int a, int b, int d) {
48} 60}
49 61
50 62
51/*
52** Returns the the previous instruction, for optimizations.
53** If there is a jump target between this and the current instruction,
54** returns a dummy instruction to avoid wrong optimizations.
55*/
56static Instruction previous_instruction (FuncState *fs) {
57 if (fs->pc > fs->lasttarget) /* no jumps to current position? */
58 return fs->f->code[fs->pc-1]; /* returns previous instruction */
59 else
60 return CREATE_0(OP_END); /* no optimizations after an `END' */
61}
62
63
64static Instruction prepare (FuncState *fs, Instruction i, int delta) { 63static Instruction prepare (FuncState *fs, Instruction i, int delta) {
65 Instruction previous = previous_instruction(fs); 64 Instruction previous = previous_instruction(fs);
66 luaK_code(fs, i, delta); 65 luaK_code(fs, i, delta);
@@ -154,7 +153,7 @@ static void luaK_setlocal (FuncState *fs, int l) {
154 153
155static void luaK_eq (FuncState *fs) { 154static void luaK_eq (FuncState *fs) {
156 /* PUSHNIL 1; JMPEQ -> NOT (a==nil) */ 155 /* PUSHNIL 1; JMPEQ -> NOT (a==nil) */
157 Instruction previous = prepare(fs, CREATE_S(OP_JMPEQ, 0), -2); 156 Instruction previous = prepare(fs, CREATE_S(OP_JMPEQ, NO_JUMP), -2);
158 if (previous == CREATE_U(OP_PUSHNIL, 1)) { 157 if (previous == CREATE_U(OP_PUSHNIL, 1)) {
159 setprevious(fs, CREATE_0(OP_NOT)); 158 setprevious(fs, CREATE_0(OP_NOT));
160 luaK_deltastack(fs, 1); /* undo delta from `prepare' */ 159 luaK_deltastack(fs, 1); /* undo delta from `prepare' */
@@ -164,13 +163,18 @@ static void luaK_eq (FuncState *fs) {
164 163
165static void luaK_neq (FuncState *fs) { 164static void luaK_neq (FuncState *fs) {
166 /* PUSHNIL 1; JMPNEQ -> JMPT (a~=nil) */ 165 /* PUSHNIL 1; JMPNEQ -> JMPT (a~=nil) */
167 Instruction previous = prepare(fs, CREATE_S(OP_JMPNEQ, 0), -2); 166 Instruction previous = prepare(fs, CREATE_S(OP_JMPNEQ, NO_JUMP), -2);
168 if (previous == CREATE_U(OP_PUSHNIL, 1)) { 167 if (previous == CREATE_U(OP_PUSHNIL, 1)) {
169 setprevious(fs, CREATE_S(OP_JMPT, 0)); 168 setprevious(fs, CREATE_S(OP_JMPT, NO_JUMP));
170 } 169 }
171} 170}
172 171
173 172
173int luaK_jump (FuncState *fs) {
174 return luaK_S(fs, OP_JMP, NO_JUMP, 0);
175}
176
177
174void luaK_retcode (FuncState *fs, int nlocals, int nexps) { 178void luaK_retcode (FuncState *fs, int nlocals, int nexps) {
175 Instruction previous = prepare(fs, CREATE_U(OP_RETURN, nlocals), 0); 179 Instruction previous = prepare(fs, CREATE_U(OP_RETURN, nlocals), 0);
176 if (nexps > 0 && GET_OPCODE(previous) == OP_CALL) { 180 if (nexps > 0 && GET_OPCODE(previous) == OP_CALL) {
@@ -192,12 +196,13 @@ static void luaK_pushnil (FuncState *fs, int n) {
192} 196}
193 197
194 198
195void luaK_fixjump (FuncState *fs, int pc, int dest) { 199static void luaK_fixjump (FuncState *fs, int pc, int dest) {
196 Instruction *jmp = &fs->f->code[pc]; 200 Instruction *jmp = &fs->f->code[pc];
197 if (dest == NO_JUMP) 201 if (dest == NO_JUMP)
198 SETARG_S(*jmp, 0); /* absolute value to represent end of list */ 202 SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */
199 else { /* jump is relative to position following jump instruction */ 203 else { /* jump is relative to position following jump instruction */
200 int offset = dest-(pc+1); 204 int offset = dest-(pc+1);
205 LUA_ASSERT(L, offset != NO_JUMP, "cannot link to itself");
201 if (abs(offset) > MAXARG_S) 206 if (abs(offset) > MAXARG_S)
202 luaK_error(fs->ls, "control structure too long"); 207 luaK_error(fs->ls, "control structure too long");
203 SETARG_S(*jmp, offset); 208 SETARG_S(*jmp, offset);
@@ -207,7 +212,7 @@ void luaK_fixjump (FuncState *fs, int pc, int dest) {
207 212
208static int luaK_getjump (FuncState *fs, int pc) { 213static int luaK_getjump (FuncState *fs, int pc) {
209 int offset = GETARG_S(fs->f->code[pc]); 214 int offset = GETARG_S(fs->f->code[pc]);
210 if (offset == 0) 215 if (offset == NO_JUMP) /* point to itself represents end of list */
211 return NO_JUMP; /* end of list */ 216 return NO_JUMP; /* end of list */
212 else 217 else
213 return (pc+1)+offset; /* turn offset into absolute position */ 218 return (pc+1)+offset; /* turn offset into absolute position */
@@ -225,11 +230,11 @@ int luaK_getlabel (FuncState *fs) {
225 230
226 231
227void luaK_deltastack (FuncState *fs, int delta) { 232void luaK_deltastack (FuncState *fs, int delta) {
228 fs->stacksize += delta; 233 fs->stacklevel += delta;
229 if (delta > 0 && fs->stacksize > fs->f->maxstacksize) { 234 if (delta > 0 && fs->stacklevel > fs->f->maxstacksize) {
230 if (fs->stacksize > MAXSTACK) 235 if (fs->stacklevel > MAXSTACK)
231 luaK_error(fs->ls, "function or expression too complex"); 236 luaK_error(fs->ls, "function or expression too complex");
232 fs->f->maxstacksize = fs->stacksize; 237 fs->f->maxstacksize = fs->stacklevel;
233 } 238 }
234} 239}
235 240
@@ -357,29 +362,16 @@ static OpCode invertjump (OpCode op) {
357} 362}
358 363
359 364
360static void luaK_jump (FuncState *fs, OpCode jump) { 365static void luaK_condjump (FuncState *fs, OpCode jump) {
361 Instruction previous = prepare(fs, CREATE_S(jump, 0), -1); 366 Instruction previous = prepare(fs, CREATE_S(jump, NO_JUMP), -1);
362 switch (GET_OPCODE(previous)) { 367 switch (GET_OPCODE(previous)) {
363 case OP_NOT: previous = CREATE_S(invertjump(jump), 0); break; 368 case OP_NOT: previous = CREATE_S(invertjump(jump), NO_JUMP); break;
364 case OP_PUSHNIL: /* optimize `repeat until nil' */
365 if (GETARG_U(previous) == 1 && jump == OP_JMPF) {
366 previous = CREATE_S(OP_JMP, 0);
367 break;
368 }
369 else return; /* do not set previous */
370 default: return; 369 default: return;
371 } 370 }
372 setprevious(fs, previous); 371 setprevious(fs, previous);
373} 372}
374 373
375 374
376static void insert_last (FuncState *fs, int *list) {
377 int first = *list;
378 *list = fs->pc-1; /* insert last instruction in the list */
379 luaK_fixjump(fs, *list, first);
380}
381
382
383static void luaK_patchlistaux (FuncState *fs, int list, int target, 375static void luaK_patchlistaux (FuncState *fs, int list, int target,
384 OpCode special, int special_target) { 376 OpCode special, int special_target) {
385 Instruction *code = fs->f->code; 377 Instruction *code = fs->f->code;
@@ -414,7 +406,7 @@ static int need_value (FuncState *fs, int list, OpCode hasvalue) {
414} 406}
415 407
416 408
417static void concatlists (FuncState *fs, int *l1, int l2) { 409void luaK_concat (FuncState *fs, int *l1, int l2) {
418 if (*l1 == NO_JUMP) 410 if (*l1 == NO_JUMP)
419 *l1 = l2; 411 *l1 = l2;
420 else { 412 else {
@@ -446,8 +438,8 @@ static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) {
446 SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); 438 SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous)));
447 } 439 }
448 else 440 else
449 luaK_jump(fs, jump); 441 luaK_condjump(fs, jump);
450 insert_last(fs, exitlist); 442 luaK_concat(fs, exitlist, fs->pc-1); /* insert last jump in `exitlist' */
451 luaK_patchlist(fs, *golist, luaK_getlabel(fs)); 443 luaK_patchlist(fs, *golist, luaK_getlabel(fs));
452 *golist = NO_JUMP; 444 *golist = NO_JUMP;
453} 445}
@@ -478,7 +470,7 @@ void luaK_tostack (LexState *ls, expdesc *v, int onlyone) {
478 int p_1 = 0; /* position of an eventual PUSHINT */ 470 int p_1 = 0; /* position of an eventual PUSHINT */
479 int final; /* position after whole expression */ 471 int final; /* position after whole expression */
480 if (ISJUMP(previous)) { 472 if (ISJUMP(previous)) {
481 insert_last(fs, &v->u.l.t); /* put `previous' in true list */ 473 luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in true list */
482 p_nil = luaK_0(fs, OP_PUSHNILJMP, 0); 474 p_nil = luaK_0(fs, OP_PUSHNILJMP, 0);
483 p_1 = luaK_S(fs, OP_PUSHINT, 1, 1); 475 p_1 = luaK_S(fs, OP_PUSHINT, 1, 1);
484 } 476 }
@@ -544,13 +536,13 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) {
544 LUA_ASSERT(ls->L, v1->u.l.t == NO_JUMP, "list must be closed"); 536 LUA_ASSERT(ls->L, v1->u.l.t == NO_JUMP, "list must be closed");
545 discharge1(fs, v2); 537 discharge1(fs, v2);
546 v1->u.l.t = v2->u.l.t; 538 v1->u.l.t = v2->u.l.t;
547 concatlists(fs, &v1->u.l.f, v2->u.l.f); 539 luaK_concat(fs, &v1->u.l.f, v2->u.l.f);
548 } 540 }
549 else if (op == TK_OR) { 541 else if (op == TK_OR) {
550 LUA_ASSERT(ls->L, v1->u.l.f == NO_JUMP, "list must be closed"); 542 LUA_ASSERT(ls->L, v1->u.l.f == NO_JUMP, "list must be closed");
551 discharge1(fs, v2); 543 discharge1(fs, v2);
552 v1->u.l.f = v2->u.l.f; 544 v1->u.l.f = v2->u.l.f;
553 concatlists(fs, &v1->u.l.t, v2->u.l.t); 545 luaK_concat(fs, &v1->u.l.t, v2->u.l.t);
554 } 546 }
555 else { 547 else {
556 luaK_tostack(ls, v2, 1); /* `v2' must be a value */ 548 luaK_tostack(ls, v2, 1); /* `v2' must be a value */
@@ -563,10 +555,10 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) {
563 case TK_CONC: luaK_conc(fs); break; 555 case TK_CONC: luaK_conc(fs); break;
564 case TK_EQ: luaK_eq(fs); break; 556 case TK_EQ: luaK_eq(fs); break;
565 case TK_NE: luaK_neq(fs); break; 557 case TK_NE: luaK_neq(fs); break;
566 case '>': luaK_S(fs, OP_JMPGT, 0, -2); break; 558 case '>': luaK_S(fs, OP_JMPGT, NO_JUMP, -2); break;
567 case '<': luaK_S(fs, OP_JMPLT, 0, -2); break; 559 case '<': luaK_S(fs, OP_JMPLT, NO_JUMP, -2); break;
568 case TK_GE: luaK_S(fs, OP_JMPGE, 0, -2); break; 560 case TK_GE: luaK_S(fs, OP_JMPGE, NO_JUMP, -2); break;
569 case TK_LE: luaK_S(fs, OP_JMPLE, 0, -2); break; 561 case TK_LE: luaK_S(fs, OP_JMPLE, NO_JUMP, -2); break;
570 } 562 }
571 } 563 }
572} 564}
diff --git a/lcode.h b/lcode.h
index ce3901db..287977d2 100644
--- a/lcode.h
+++ b/lcode.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.h,v 1.8 2000/03/15 20:50:33 roberto Exp roberto $ 2** $Id: lcode.h,v 1.9 2000/03/17 13:09:46 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -13,6 +13,9 @@
13#include "lparser.h" 13#include "lparser.h"
14 14
15 15
16#define NO_JUMP (-1) /* marks end of patch list */
17
18
16void luaK_error (LexState *ls, const char *msg); 19void luaK_error (LexState *ls, const char *msg);
17int luaK_0(FuncState *fs, OpCode o, int d); 20int luaK_0(FuncState *fs, OpCode o, int d);
18int luaK_U(FuncState *fs, OpCode o, int u, int d); 21int luaK_U(FuncState *fs, OpCode o, int u, int d);
@@ -20,8 +23,9 @@ int luaK_S(FuncState *fs, OpCode o, int s, int d);
20int luaK_AB(FuncState *fs, OpCode o, int a, int b, int d); 23int luaK_AB(FuncState *fs, OpCode o, int a, int b, int d);
21int luaK_code (FuncState *fs, Instruction i, int delta); 24int luaK_code (FuncState *fs, Instruction i, int delta);
22void luaK_retcode (FuncState *fs, int nlocals, int nexps); 25void luaK_retcode (FuncState *fs, int nlocals, int nexps);
23void luaK_fixjump (FuncState *fs, int pc, int dest); 26int luaK_jump (FuncState *fs);
24void luaK_patchlist (FuncState *fs, int list, int target); 27void luaK_patchlist (FuncState *fs, int list, int target);
28void luaK_concat (FuncState *fs, int *l1, int l2);
25void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); 29void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue);
26void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue); 30void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue);
27int luaK_getlabel (FuncState *fs); 31int luaK_getlabel (FuncState *fs);
diff --git a/llex.c b/llex.c
index f56b0a21..ec8231a2 100644
--- a/llex.c
+++ b/llex.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llex.c,v 1.53 2000/03/10 18:37:44 roberto Exp roberto $ 2** $Id: llex.c,v 1.54 2000/03/24 17:26:08 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*/
@@ -31,7 +31,8 @@
31 31
32 32
33/* ORDER RESERVED */ 33/* ORDER RESERVED */
34static const char *const token2string [] = {"and", "do", "else", "elseif", "end", 34static const char *const token2string [] = {
35 "and", "break", "do", "else", "elseif", "end",
35 "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", 36 "function", "if", "local", "nil", "not", "or", "repeat", "return", "then",
36 "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", "<eof>"}; 37 "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", "<eof>"};
37 38
diff --git a/llex.h b/llex.h
index 87e6511a..a09da136 100644
--- a/llex.h
+++ b/llex.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llex.h,v 1.20 2000/03/10 18:37:44 roberto Exp roberto $ 2** $Id: llex.h,v 1.21 2000/03/24 17:26:08 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*/
@@ -23,7 +23,7 @@
23*/ 23*/
24enum RESERVED { 24enum RESERVED {
25 /* terminal symbols denoted by reserved words */ 25 /* terminal symbols denoted by reserved words */
26 TK_AND = FIRST_RESERVED, 26 TK_AND = FIRST_RESERVED, TK_BREAK,
27 TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FUNCTION, TK_IF, TK_LOCAL, 27 TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FUNCTION, TK_IF, TK_LOCAL,
28 TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE, 28 TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE,
29 /* other terminal symbols */ 29 /* other terminal symbols */
diff --git a/lparser.c b/lparser.c
index 05832288..1bb0c0cc 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 1.74 2000/03/29 20:19:20 roberto Exp roberto $ 2** $Id: lparser.c,v 1.75 2000/04/03 13:44:55 roberto Exp roberto $
3** LL(1) Parser and code generator for Lua 3** LL(1) Parser and code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -28,10 +28,17 @@
28** it is a list constructor (k = 0) or a record constructor (k = 1) 28** it is a list constructor (k = 0) or a record constructor (k = 1)
29** or empty (k = ';' or '}') 29** or empty (k = ';' or '}')
30*/ 30*/
31typedef struct constdesc { 31typedef struct Constdesc {
32 int n; 32 int n;
33 int k; 33 int k;
34} constdesc; 34} Constdesc;
35
36
37typedef struct Breaklabel {
38 struct Breaklabel *previous; /* chain */
39 int breaklist;
40 int stacklevel;
41} Breaklabel;
35 42
36 43
37 44
@@ -311,6 +318,21 @@ static int getvarname (LexState *ls, expdesc *var) {
311} 318}
312 319
313 320
321static void enterbreak (FuncState *fs, Breaklabel *bl) {
322 bl->stacklevel = fs->stacklevel;
323 bl->breaklist = NO_JUMP;
324 bl->previous = fs->bl;
325 fs->bl = bl;
326}
327
328
329static void leavebreak (FuncState *fs, Breaklabel *bl) {
330 fs->bl = bl->previous;
331 LUA_ASSERT(fs->L, bl->stacklevel == fs->stacklevel, "wrong levels");
332 luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs));
333}
334
335
314static void func_onstack (LexState *ls, FuncState *func) { 336static void func_onstack (LexState *ls, FuncState *func) {
315 FuncState *fs = ls->fs; 337 FuncState *fs = ls->fs;
316 Proto *f = fs->f; 338 Proto *f = fs->f;
@@ -332,10 +354,11 @@ static void init_state (LexState *ls, FuncState *fs, TString *source) {
332 fs->ls = ls; 354 fs->ls = ls;
333 fs->L = ls->L; 355 fs->L = ls->L;
334 ls->fs = fs; 356 ls->fs = fs;
335 fs->stacksize = 0; 357 fs->stacklevel = 0;
336 fs->nlocalvar = 0; 358 fs->nlocalvar = 0;
337 fs->nupvalues = 0; 359 fs->nupvalues = 0;
338 fs->lastsetline = 0; 360 fs->lastsetline = 0;
361 fs->bl = NULL;
339 fs->f = f; 362 fs->f = f;
340 f->source = source; 363 f->source = source;
341 fs->pc = 0; 364 fs->pc = 0;
@@ -362,6 +385,7 @@ static void close_func (LexState *ls) {
362 luaM_reallocvector(L, f->locvars, fs->nvars, LocVar); 385 luaM_reallocvector(L, f->locvars, fs->nvars, LocVar);
363 } 386 }
364 ls->fs = fs->prev; 387 ls->fs = fs->prev;
388 LUA_ASSERT(L, fs->bl == NULL, "wrong list end");
365} 389}
366 390
367 391
@@ -375,6 +399,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) {
375 if (lexstate.token != TK_EOS) 399 if (lexstate.token != TK_EOS)
376 luaK_error(&lexstate, "<eof> expected"); 400 luaK_error(&lexstate, "<eof> expected");
377 close_func(&lexstate); 401 close_func(&lexstate);
402 LUA_ASSERT(L, funcstate.prev == NULL, "wrong list end");
378 return funcstate.f; 403 return funcstate.f;
379} 404}
380 405
@@ -416,7 +441,7 @@ static int explist (LexState *ls) {
416 441
417static void funcargs (LexState *ls, int slf) { 442static void funcargs (LexState *ls, int slf) {
418 FuncState *fs = ls->fs; 443 FuncState *fs = ls->fs;
419 int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ 444 int slevel = fs->stacklevel - slf - 1; /* where is func in the stack */
420 switch (ls->token) { 445 switch (ls->token) {
421 case '(': { /* funcargs -> '(' explist ')' */ 446 case '(': { /* funcargs -> '(' explist ')' */
422 int line = ls->linenumber; 447 int line = ls->linenumber;
@@ -444,7 +469,7 @@ static void funcargs (LexState *ls, int slf) {
444 luaK_error(ls, "function arguments expected"); 469 luaK_error(ls, "function arguments expected");
445 break; 470 break;
446 } 471 }
447 fs->stacksize = slevel; /* call will remove function and arguments */ 472 fs->stacklevel = slevel; /* call will remove function and arguments */
448 luaK_AB(fs, OP_CALL, slevel, MULT_RET, 0); 473 luaK_AB(fs, OP_CALL, slevel, MULT_RET, 0);
449} 474}
450 475
@@ -581,7 +606,7 @@ static int listfields (LexState *ls) {
581 606
582 607
583 608
584static void constructor_part (LexState *ls, constdesc *cd) { 609static void constructor_part (LexState *ls, Constdesc *cd) {
585 switch (ls->token) { 610 switch (ls->token) {
586 case ';': case '}': /* constructor_part -> empty */ 611 case ';': case '}': /* constructor_part -> empty */
587 cd->n = 0; 612 cd->n = 0;
@@ -627,12 +652,12 @@ static void constructor (LexState *ls) {
627 int line = ls->linenumber; 652 int line = ls->linenumber;
628 int pc = luaK_U(fs, OP_CREATETABLE, 0, 1); 653 int pc = luaK_U(fs, OP_CREATETABLE, 0, 1);
629 int nelems; 654 int nelems;
630 constdesc cd; 655 Constdesc cd;
631 check(ls, '{'); 656 check(ls, '{');
632 constructor_part(ls, &cd); 657 constructor_part(ls, &cd);
633 nelems = cd.n; 658 nelems = cd.n;
634 if (ls->token == ';') { 659 if (ls->token == ';') {
635 constdesc other_cd; 660 Constdesc other_cd;
636 next(ls); 661 next(ls);
637 constructor_part(ls, &other_cd); 662 constructor_part(ls, &other_cd);
638 if (cd.k == other_cd.k) /* repeated parts? */ 663 if (cd.k == other_cd.k) /* repeated parts? */
@@ -825,14 +850,17 @@ static void whilestat (LexState *ls, int line) {
825 FuncState *fs = ls->fs; 850 FuncState *fs = ls->fs;
826 int while_init = luaK_getlabel(fs); 851 int while_init = luaK_getlabel(fs);
827 expdesc v; 852 expdesc v;
853 Breaklabel bl;
854 enterbreak(fs, &bl);
828 setline_and_next(ls); /* trace WHILE when looping */ 855 setline_and_next(ls); /* trace WHILE when looping */
829 expr(ls, &v); /* read condition */ 856 expr(ls, &v); /* read condition */
830 luaK_goiftrue(fs, &v, 0); 857 luaK_goiftrue(fs, &v, 0);
831 check(ls, TK_DO); 858 check(ls, TK_DO);
832 block(ls); 859 block(ls);
833 luaK_fixjump(fs, luaK_S(fs, OP_JMP, 0, 0), while_init); 860 luaK_patchlist(fs, luaK_jump(fs), while_init);
834 luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); 861 luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs));
835 check_END(ls, TK_WHILE, line); 862 check_END(ls, TK_WHILE, line);
863 leavebreak(fs, &bl);
836} 864}
837 865
838 866
@@ -841,12 +869,55 @@ static void repeatstat (LexState *ls, int line) {
841 FuncState *fs = ls->fs; 869 FuncState *fs = ls->fs;
842 int repeat_init = luaK_getlabel(fs); 870 int repeat_init = luaK_getlabel(fs);
843 expdesc v; 871 expdesc v;
872 Breaklabel bl;
873 enterbreak(fs, &bl);
844 setline_and_next(ls); /* trace REPEAT when looping */ 874 setline_and_next(ls); /* trace REPEAT when looping */
845 block(ls); 875 block(ls);
846 check_match(ls, TK_UNTIL, TK_REPEAT, line); 876 if (ls->token == TK_END) {
847 expr(ls, &v); 877 luaK_patchlist(fs, luaK_jump(fs), repeat_init);
848 luaK_goiftrue(fs, &v, 0); 878 next(ls);
849 luaK_patchlist(fs, v.u.l.f, repeat_init); 879 }
880 else {
881 check_match(ls, TK_UNTIL, TK_REPEAT, line);
882 expr(ls, &v);
883 luaK_goiftrue(fs, &v, 0);
884 luaK_patchlist(fs, v.u.l.f, repeat_init);
885 }
886 leavebreak(fs, &bl);
887}
888
889
890static void test_and_bock (LexState *ls, expdesc *v) {
891 setline_and_next(ls); /* skip IF or ELSEIF */
892 expr(ls, v); /* cond */
893 luaK_goiftrue(ls->fs, v, 0);
894 setline(ls); /* to trace the THEN */
895 check(ls, TK_THEN);
896 block(ls); /* `then' part */
897}
898
899
900static void ifstat (LexState *ls, int line) {
901 /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
902 FuncState *fs = ls->fs;
903 expdesc v;
904 int escapelist = NO_JUMP;
905 test_and_bock(ls, &v); /* IF cond THEN block */
906 while (ls->token == TK_ELSEIF) {
907 luaK_concat(fs, &escapelist, luaK_jump(fs));
908 luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs));
909 test_and_bock(ls, &v); /* ELSEIF cond THEN block */
910 }
911 if (ls->token == TK_ELSE) {
912 luaK_concat(fs, &escapelist, luaK_jump(fs));
913 luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs));
914 setline_and_next(ls); /* skip ELSE */
915 block(ls); /* `else' part */
916 }
917 else
918 luaK_concat(fs, &escapelist, v.u.l.f);
919 luaK_patchlist(fs, escapelist, luaK_getlabel(fs));
920 check_END(ls, TK_IF, line);
850} 921}
851 922
852 923
@@ -932,42 +1003,11 @@ static void namestat (LexState *ls) {
932} 1003}
933 1004
934 1005
935static void ifpart (LexState *ls) {
936 /* ifpart -> cond THEN block (ELSEIF ifpart | [ELSE block] END) */
937 FuncState *fs = ls->fs;
938 expdesc v;
939 int elseinit;
940 setline_and_next(ls); /* skip IF or ELSEIF */
941 expr(ls, &v); /* cond */
942 luaK_goiftrue(fs, &v, 0);
943 setline(ls); /* to trace the THEN */
944 check(ls, TK_THEN);
945 block(ls); /* `then' part */
946 luaK_S(fs, OP_JMP, 0, 0); /* 2nd jump: over `else' part */
947 elseinit = luaK_getlabel(fs); /* address of 2nd jump == elseinit-1 */
948 if (ls->token == TK_ELSEIF)
949 ifpart(ls);
950 else if (ls->token == TK_ELSE) {
951 setline_and_next(ls); /* skip ELSE */
952 block(ls); /* `else' part */
953 }
954 if (fs->pc > elseinit) { /* is there an `else' part? */
955 luaK_fixjump(fs, elseinit-1, luaK_getlabel(fs)); /* fix 2nd jump */
956 }
957 else { /* no else part */
958 fs->pc--; /* remove 2nd jump */
959 elseinit = luaK_getlabel(fs); /* `elseinit' points to end */
960 }
961 luaK_patchlist(fs, v.u.l.f, elseinit); /* fix 1st jump to `else' part */
962}
963
964
965static int stat (LexState *ls) { 1006static int stat (LexState *ls) {
966 int line = ls->linenumber; /* may be needed for error messages */ 1007 int line = ls->linenumber; /* may be needed for error messages */
967 switch (ls->token) { 1008 switch (ls->token) {
968 case TK_IF: /* stat -> IF ifpart END */ 1009 case TK_IF: /* stat -> ifstat */
969 ifpart(ls); 1010 ifstat(ls, line);
970 check_END(ls, TK_IF, line);
971 break; 1011 break;
972 1012
973 case TK_WHILE: /* stat -> whilestat */ 1013 case TK_WHILE: /* stat -> whilestat */
@@ -1058,15 +1098,30 @@ static void body (LexState *ls, int needself, int line) {
1058 1098
1059 1099
1060static void ret (LexState *ls) { 1100static void ret (LexState *ls) {
1061 /* ret -> [RETURN explist sc] */ 1101 /* ret -> [RETURN explist sc | BREAK sc] */
1062 if (ls->token == TK_RETURN) { 1102 FuncState *fs = ls->fs;
1063 FuncState *fs = ls->fs; 1103 switch (ls->token) {
1064 int nexps; /* number of expressions returned */ 1104 case TK_RETURN: {
1065 setline_and_next(ls); /* skip RETURN */ 1105 int nexps; /* number of expressions returned */
1066 nexps = explist(ls); 1106 setline_and_next(ls); /* skip RETURN */
1067 luaK_retcode(fs, ls->fs->nlocalvar, nexps); 1107 nexps = explist(ls);
1068 fs->stacksize = fs->nlocalvar; /* removes all temp values */ 1108 luaK_retcode(fs, ls->fs->nlocalvar, nexps);
1069 optional(ls, ';'); 1109 fs->stacklevel = fs->nlocalvar; /* removes all temp values */
1110 optional(ls, ';');
1111 break;
1112 }
1113 case TK_BREAK: {
1114 Breaklabel *bl = fs->bl;
1115 int currentlevel = fs->stacklevel;
1116 if (bl == NULL)
1117 luaK_error(ls, "no breakable structure to break");
1118 setline_and_next(ls); /* skip BREAK */
1119 luaK_adjuststack(fs, currentlevel - bl->stacklevel);
1120 luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
1121 optional(ls, ';');
1122 fs->stacklevel = currentlevel;
1123 break;
1124 }
1070 } 1125 }
1071} 1126}
1072 1127
@@ -1076,7 +1131,7 @@ static void ret (LexState *ls) {
1076static void chunk (LexState *ls) { 1131static void chunk (LexState *ls) {
1077 /* chunk -> { stat [;] } ret */ 1132 /* chunk -> { stat [;] } ret */
1078 while (stat(ls)) { 1133 while (stat(ls)) {
1079 LUA_ASSERT(ls->L, ls->fs->stacksize == ls->fs->nlocalvar, 1134 LUA_ASSERT(ls->L, ls->fs->stacklevel == ls->fs->nlocalvar,
1080 "stack size != # local vars"); 1135 "stack size != # local vars");
1081 optional(ls, ';'); 1136 optional(ls, ';');
1082 } 1137 }
diff --git a/lparser.h b/lparser.h
index 896b1eb9..64214861 100644
--- a/lparser.h
+++ b/lparser.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.h,v 1.13 2000/03/13 20:37:16 roberto Exp roberto $ 2** $Id: lparser.h,v 1.14 2000/03/24 17:26:08 roberto Exp roberto $
3** LL(1) Parser and code generator for Lua 3** LL(1) Parser and code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -34,8 +34,6 @@ typedef struct expdesc {
34} expdesc; 34} expdesc;
35 35
36 36
37#define NO_JUMP (-1) /* marks end of patch list */
38
39 37
40/* state needed to generate code for a given function */ 38/* state needed to generate code for a given function */
41typedef struct FuncState { 39typedef struct FuncState {
@@ -45,11 +43,12 @@ typedef struct FuncState {
45 struct lua_State *L; /* copy of the Lua state */ 43 struct lua_State *L; /* copy of the Lua state */
46 int pc; /* next position to code */ 44 int pc; /* next position to code */
47 int lasttarget; /* `pc' of last `jump target' */ 45 int lasttarget; /* `pc' of last `jump target' */
48 int stacksize; /* number of values on activation register */ 46 int stacklevel; /* number of values on activation register */
49 int nlocalvar; /* number of active local variables */ 47 int nlocalvar; /* number of active local variables */
50 int nupvalues; /* number of upvalues */ 48 int nupvalues; /* number of upvalues */
51 int nvars; /* number of entries in f->locvars (-1 if no debug information) */ 49 int nvars; /* number of entries in f->locvars (-1 if no debug information) */
52 int lastsetline; /* line where last SETLINE was issued */ 50 int lastsetline; /* line where last SETLINE was issued */
51 struct Breaklabel *bl; /* chain of breakable blocks */
53 expdesc upvalues[MAXUPVALUES]; /* upvalues */ 52 expdesc upvalues[MAXUPVALUES]; /* upvalues */
54 TString *localvar[MAXLOCALS]; /* store local variable names */ 53 TString *localvar[MAXLOCALS]; /* store local variable names */
55} FuncState; 54} FuncState;